Skip to main content

Select Navigation (Internal) v1.8.0

Allow user to choose an item from a select menu, updating the content on the same page.

Default Setup Anchor (Default Setup)

User Interface Developer

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.

<div class="select-internal">

  <nav aria-label="Job Positions" class="select-internal__nav">

    <label class="select-internal__label">Select your job position</label>

    <select class="select-internal__select">
        <option value="#uid">User Interface Developer</option>
        <option value="#a11y-director">Director, Accessibility</option>
        <option value="#chief-cook">Chief Cook & Bottle Washer</option>
    </select>

    <div class="visually-hidden" aria-live="polite"></div>

  </nav>

  <div class="select-internal__content" id="uid">

    <h2>User Interface Developer</h2>

    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, <a href="#">tempor sit amet</a>, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>

  </div>

  <div class="select-internal__content" hidden id="a11y-director">

    <h2>Director, Accessibility</h2>

    <p>Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>

  </div>

  <div class="select-internal__content" hidden id="chief-cook">

    <h2>Chief Cook & Bottle Washer</h2>

    <p>Pellentesque habitant <a href="#a11y-director">Accessibility Director</a> et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante.</p>

    <ul>
      <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
      <li>Aliquam tincidunt mauris eu risus.</li>
      <li>Vestibulum auctor dapibus neque.</li>
    </ul>

  </div>

</div>
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

  Dependencies: Sass

*/

.select-internal {
  
  &__nav {
  background-color: #eee;
  border-radius: .5em;
  display: grid;
  gap: .5em;
  max-inline-size: calc(420rem / 16);
  padding: 1em;
  }
  
  &__label {
  font-weight: bold;
  margin: 0;
  }

  &__select {
  background-color: #FFF;
  border: 1px #ccc solid;
  font-size: inherit;
  padding: .5em;
  inline-size: 100%;
  }

  &__content {
  margin-block-start: 2em;
    
    &:target {
    scroll-margin-top: calc(190em / 16);
    }
  
  }

  // Custom Select 

  &[data-custom-select] {

    --select-primary-color: #6F00EF;
    --select-border-radius: calc(5rem / 16);

    .select-internal__select, ::picker(select) {

      appearance: base-select;
      line-height: normal;

    }

    .select-internal__select {
    border-radius: var(--select-border-radius);

      &:focus-visible {
      outline: calc(2rem / 16) var(--select-primary-color) solid;
      outline-offset: calc(2rem / 16);
      }

      &::picker-icon {
      color: var(--select-primary-color);
      transition: .4s rotate;
      }

      &:open::picker-icon {
      rotate: 180deg;
      }

      optgroup {
        
        option {
        margin-inline-start: 1rem;
        }

      }

      legend {
      color: var(--select-primary-color);
      margin-block: 1rem;
      }

      option {
      border-radius: var(--select-border-radius);
      margin-block-end: calc(8rem / 16);
      padding: calc(8rem / 16) calc(8rem / 16) calc(8rem / 16) 1rem;
      
        &::checkmark {
        border-radius: 100vw;
        border: calc(2rem / 16) #fff solid;
        color: #fff;
        font-weight: bold;
        margin-inline-start: auto;
        order: 1;
        padding: calc(3rem / 16) calc(8rem / 16);
        }

        &[value=""] {
        background-color: #eee;

          &:not(:hover):not(:focus) {

            &::checkmark {
            border-color: #000;
            color: #000;
            }

          }

        }

        &:focus, &:hover {
        outline: 0;
        color: #fff;
        background-color: var(--select-primary-color);
        }

      }

    }

    // This is the select dropdown

    ::picker(select) {
    border-radius: var(--select-border-radius);
    border: calc(1rem / 16) #666 solid;
    box-shadow: 0 calc(4rem / 16) calc(16rem / 16) rgb(0 0 0 / .8);
    margin: 1rem 1rem 0 0;
    padding: 1rem;
    scrollbar-color: var(--select-primary-color) transparent;
    scrollbar-width: thin;
    }

  }
  
}
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

*/

(function() {

  "use strict";

  // Display which component is in use via console:

  console.log("%cSelect Navigation (Internal)%cv1.8.0", "background: #2d2d2d; color: #fff; padding: 6px 10px; border-radius: 16px 0 0 16px; font-weight: 600;" , "background: #6e00ee; color: #fff; padding: 6px 10px; border-radius: 0 16px 16px 0; font-weight: 600;");

  var selectInternalClass = ".select-internal";
  var selectInternalLabelClass = ".select-internal__label";
  var selectInternalSelectClass = ".select-internal__select";
  var selectInternalOptionClass = ".select-internal__select option";
  var selectInternalContentClass = ".select-internal__content";
  var selectInternalDataCustomAriaLive = "data-aria-live";
  var selectInternal = document.querySelectorAll(selectInternalClass);
  var selectInternalLabel = document.querySelectorAll(selectInternalLabelClass);
  var selectInternalSelect = document.querySelectorAll(selectInternalSelectClass);
  var selectInternalState = "active";
  var selectInternalContentList = [];

  // On page load

  selectInternal.forEach(function(component) {

    // Check if "dynamic" Jump Menu is in use.

    if (component.hasAttribute("data-dynamic")) {

      var selectInternalContent = component.querySelectorAll(selectInternalContentClass);
      var selectInternalContentNth = component.querySelectorAll(selectInternalContentClass + ":nth-of-type(n + 2)");

      selectInternalContentNth.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      selectInternalContent.forEach(function(content, i) {

        var count = i + 1;

        // If custom ID present

        var contentID = content.hasAttribute("data-id") ? content.getAttribute("data-id"): "content-" + count;

        content.setAttribute("id", contentID);

        // Create option element

        var option = document.createElement("option");

        option.setAttribute("value", "#" + contentID);
        option.textContent = content.getAttribute("data-label");

        // Append each dynamic option.

        component.querySelector("select").appendChild(option);

      });

    }

  });

  var selectInternalOption = document.querySelectorAll(selectInternalOptionClass);

  selectInternalLabel.forEach(function(label, e) {

    // Apply "for" attribute to each label.

    label.setAttribute("for", "select-internal-" + (e + 1));

  });

  selectInternalSelect.forEach(function(select, e) {

    // Apply "id" to each select.

    select.setAttribute("id", "select-internal-" + (e + 1));

  });

  // Get all Job Menu options on page and push to array.

  selectInternalOption.forEach(function(option) {

    selectInternalContentList.push(option.getAttribute("value"));

  });

  function selectInternalSelectedState() {

    var selectInternalHash = location.hash || selectInternalContentList[0];

    if (!selectInternalHash) {

      return;
    
    }

    var selectInternalFragment = selectInternalHash.slice(1);

    // Check array against hash

    if (selectInternalContentList.includes(selectInternalHash)) {

      // If hash matches one of the array selections, load the selected content in hash
    
      var selectInternalSelected = document.getElementById(selectInternalFragment);
      var selectInternalContent = selectInternalSelected.closest(selectInternalClass).querySelectorAll(selectInternalContentClass);

      selectInternalContent.forEach(function(content) {
      
        content.setAttribute("hidden", "");

      });

      selectInternalSelected.removeAttribute("hidden");

      selectInternalOption.forEach(function(option) {

        var optionValue = option.getAttribute("value");

        if (location.hash === optionValue) {

          option.setAttribute("selected", "");
          option.closest(selectInternalClass).classList.add(selectInternalState);

        } else {

          option.removeAttribute("selected");

        }

      });

      // Update select dropdown

      var select = document.querySelector(selectInternalClass + " select");

      if (select) {

        select.value = selectInternalHash;

      }

    }

  }

  selectInternalSelectedState();

  // Hash change event listener
  
  window.addEventListener("hashchange", function() {

    selectInternalSelectedState();

    // When link is pressed, place programatic focus on selected content. This is useful if links are elsewhere on the page.
    // If this causes issues elsewhere on page when haschange is fired, let me know.

    var selectedContent = document.querySelector(selectInternalContentClass + ":not([hidden])");
    var selectedContentID = selectedContent.getAttribute("id");
    var URLHash = location.hash.slice(1);

    if(URLHash === selectedContentID) {

      selectedContent.setAttribute("tabindex", "-1");
      selectedContent.focus();

    }

  });

  selectInternalSelect.forEach(function(select) {

    select.addEventListener("change", function() {

      var selectInternalParent = this.closest(selectInternalClass);
      var selectInternalContent = selectInternalParent.querySelectorAll(selectInternalContentClass);

      // Send message to screen reader.

      var selectInternalAnnounce = selectInternalParent.querySelector("div[aria-live]");

      if(!selectInternalParent.hasAttribute(selectInternalDataCustomAriaLive)){

        selectInternalAnnounce.textContent = "Selected Content: " + this.options[this.selectedIndex].text; // TODO: Tokenize for i18n.

      }

      // Update hash in URL

      if (this.value === "") {

        var urlWithoutHash = window.location.href.split("#")[0];
        
        history.replaceState(null, null, urlWithoutHash);

        selectInternalAnnounce.textContent = "";

      } else {

        history.replaceState(null, null, this.value);

      }

      selectInternalContent.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      var selectInternalContentSelected = location.hash.slice(1);

      document.getElementById(selectInternalContentSelected).removeAttribute("hidden");

      // Set selected jump menu to active.

      selectInternal.forEach(function(menu) {

        menu.classList.remove(selectInternalState);

      });

      selectInternalParent.classList.add(selectInternalState);

    });

  });

  // Fix for some browsers not resetting the select index on page unload.

  window.addEventListener("beforeunload", function() {

    selectInternal.forEach(function(menu) {

      if (!menu.classList.contains(selectInternalState)) {

        menu.querySelector("select").selectedIndex = 0;

      }

    });

  });

})();

Custom Aria-Live Setup Anchor (Custom Aria-Live Setup)

Harry Potter

Expecto Patronum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.

<div class="select-internal" data-aria-live>

    <nav aria-label="Favorite Movies" class="select-internal__nav">
  
      <label class="select-internal__label">Select your favorite movie franchise</label>
  
      <select class="select-internal__select">
          <option value="#harry-potter">Harry Potter</option>
          <option value="#marvel">Marvel</option>
          <option value="#star-trek">Star Trek</option>
          <option value="#star-wars">Star Wars</option>
      </select>
  
    </nav>
  
    <div aria-live="polite">
  
      <div class="select-internal__content" id="harry-potter">
  
        <h2>Harry Potter</h2>
  
        <p>Expecto Patronum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
  
      </div>
  
      <div class="select-internal__content" hidden id="marvel">
  
        <h2>Marvel</h2>
  
        <p>Pellentesque habitant <a href="#!">morbi tristique senectus</a> tempor sit amet, ante. Donec eu libero sit amet quam egestas 3000.</p>
  
      </div>
  
      <div class="select-internal__content" hidden id="star-trek">
  
        <h2>Star Trek</h2>
  
        <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, <a href="#!">U.S.S. Enterprise</a>, ante. Donec eu libero sit amet.</p>
  
      </div>
  
      <div class="select-internal__content" hidden id="star-wars">
  
        <h2>Star Wars</h2>
  
        <p>Senectus et netus et the force fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, <a href="#!">Sidious</a>, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
  
      </div>
  
    </div>
  
  </div>
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

  Dependencies: Sass

*/

.select-internal {
  
  &__nav {
  background-color: #eee;
  border-radius: .5em;
  display: grid;
  gap: .5em;
  max-inline-size: calc(420rem / 16);
  padding: 1em;
  }
  
  &__label {
  font-weight: bold;
  margin: 0;
  }

  &__select {
  background-color: #FFF;
  border: 1px #ccc solid;
  font-size: inherit;
  padding: .5em;
  inline-size: 100%;
  }

  &__content {
  margin-block-start: 2em;
    
    &:target {
    scroll-margin-top: calc(190em / 16);
    }
  
  }

  // Custom Select 

  &[data-custom-select] {

    --select-primary-color: #6F00EF;
    --select-border-radius: calc(5rem / 16);

    .select-internal__select, ::picker(select) {

      appearance: base-select;
      line-height: normal;

    }

    .select-internal__select {
    border-radius: var(--select-border-radius);

      &:focus-visible {
      outline: calc(2rem / 16) var(--select-primary-color) solid;
      outline-offset: calc(2rem / 16);
      }

      &::picker-icon {
      color: var(--select-primary-color);
      transition: .4s rotate;
      }

      &:open::picker-icon {
      rotate: 180deg;
      }

      optgroup {
        
        option {
        margin-inline-start: 1rem;
        }

      }

      legend {
      color: var(--select-primary-color);
      margin-block: 1rem;
      }

      option {
      border-radius: var(--select-border-radius);
      margin-block-end: calc(8rem / 16);
      padding: calc(8rem / 16) calc(8rem / 16) calc(8rem / 16) 1rem;
      
        &::checkmark {
        border-radius: 100vw;
        border: calc(2rem / 16) #fff solid;
        color: #fff;
        font-weight: bold;
        margin-inline-start: auto;
        order: 1;
        padding: calc(3rem / 16) calc(8rem / 16);
        }

        &[value=""] {
        background-color: #eee;

          &:not(:hover):not(:focus) {

            &::checkmark {
            border-color: #000;
            color: #000;
            }

          }

        }

        &:focus, &:hover {
        outline: 0;
        color: #fff;
        background-color: var(--select-primary-color);
        }

      }

    }

    // This is the select dropdown

    ::picker(select) {
    border-radius: var(--select-border-radius);
    border: calc(1rem / 16) #666 solid;
    box-shadow: 0 calc(4rem / 16) calc(16rem / 16) rgb(0 0 0 / .8);
    margin: 1rem 1rem 0 0;
    padding: 1rem;
    scrollbar-color: var(--select-primary-color) transparent;
    scrollbar-width: thin;
    }

  }
  
}
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

*/

(function() {

  "use strict";

  // Display which component is in use via console:

  console.log("%cSelect Navigation (Internal)%cv1.8.0", "background: #2d2d2d; color: #fff; padding: 6px 10px; border-radius: 16px 0 0 16px; font-weight: 600;" , "background: #6e00ee; color: #fff; padding: 6px 10px; border-radius: 0 16px 16px 0; font-weight: 600;");

  var selectInternalClass = ".select-internal";
  var selectInternalLabelClass = ".select-internal__label";
  var selectInternalSelectClass = ".select-internal__select";
  var selectInternalOptionClass = ".select-internal__select option";
  var selectInternalContentClass = ".select-internal__content";
  var selectInternalDataCustomAriaLive = "data-aria-live";
  var selectInternal = document.querySelectorAll(selectInternalClass);
  var selectInternalLabel = document.querySelectorAll(selectInternalLabelClass);
  var selectInternalSelect = document.querySelectorAll(selectInternalSelectClass);
  var selectInternalState = "active";
  var selectInternalContentList = [];

  // On page load

  selectInternal.forEach(function(component) {

    // Check if "dynamic" Jump Menu is in use.

    if (component.hasAttribute("data-dynamic")) {

      var selectInternalContent = component.querySelectorAll(selectInternalContentClass);
      var selectInternalContentNth = component.querySelectorAll(selectInternalContentClass + ":nth-of-type(n + 2)");

      selectInternalContentNth.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      selectInternalContent.forEach(function(content, i) {

        var count = i + 1;

        // If custom ID present

        var contentID = content.hasAttribute("data-id") ? content.getAttribute("data-id"): "content-" + count;

        content.setAttribute("id", contentID);

        // Create option element

        var option = document.createElement("option");

        option.setAttribute("value", "#" + contentID);
        option.textContent = content.getAttribute("data-label");

        // Append each dynamic option.

        component.querySelector("select").appendChild(option);

      });

    }

  });

  var selectInternalOption = document.querySelectorAll(selectInternalOptionClass);

  selectInternalLabel.forEach(function(label, e) {

    // Apply "for" attribute to each label.

    label.setAttribute("for", "select-internal-" + (e + 1));

  });

  selectInternalSelect.forEach(function(select, e) {

    // Apply "id" to each select.

    select.setAttribute("id", "select-internal-" + (e + 1));

  });

  // Get all Job Menu options on page and push to array.

  selectInternalOption.forEach(function(option) {

    selectInternalContentList.push(option.getAttribute("value"));

  });

  function selectInternalSelectedState() {

    var selectInternalHash = location.hash || selectInternalContentList[0];

    if (!selectInternalHash) {

      return;
    
    }

    var selectInternalFragment = selectInternalHash.slice(1);

    // Check array against hash

    if (selectInternalContentList.includes(selectInternalHash)) {

      // If hash matches one of the array selections, load the selected content in hash
    
      var selectInternalSelected = document.getElementById(selectInternalFragment);
      var selectInternalContent = selectInternalSelected.closest(selectInternalClass).querySelectorAll(selectInternalContentClass);

      selectInternalContent.forEach(function(content) {
      
        content.setAttribute("hidden", "");

      });

      selectInternalSelected.removeAttribute("hidden");

      selectInternalOption.forEach(function(option) {

        var optionValue = option.getAttribute("value");

        if (location.hash === optionValue) {

          option.setAttribute("selected", "");
          option.closest(selectInternalClass).classList.add(selectInternalState);

        } else {

          option.removeAttribute("selected");

        }

      });

      // Update select dropdown

      var select = document.querySelector(selectInternalClass + " select");

      if (select) {

        select.value = selectInternalHash;

      }

    }

  }

  selectInternalSelectedState();

  // Hash change event listener
  
  window.addEventListener("hashchange", function() {

    selectInternalSelectedState();

    // When link is pressed, place programatic focus on selected content. This is useful if links are elsewhere on the page.
    // If this causes issues elsewhere on page when haschange is fired, let me know.

    var selectedContent = document.querySelector(selectInternalContentClass + ":not([hidden])");
    var selectedContentID = selectedContent.getAttribute("id");
    var URLHash = location.hash.slice(1);

    if(URLHash === selectedContentID) {

      selectedContent.setAttribute("tabindex", "-1");
      selectedContent.focus();

    }

  });

  selectInternalSelect.forEach(function(select) {

    select.addEventListener("change", function() {

      var selectInternalParent = this.closest(selectInternalClass);
      var selectInternalContent = selectInternalParent.querySelectorAll(selectInternalContentClass);

      // Send message to screen reader.

      var selectInternalAnnounce = selectInternalParent.querySelector("div[aria-live]");

      if(!selectInternalParent.hasAttribute(selectInternalDataCustomAriaLive)){

        selectInternalAnnounce.textContent = "Selected Content: " + this.options[this.selectedIndex].text; // TODO: Tokenize for i18n.

      }

      // Update hash in URL

      if (this.value === "") {

        var urlWithoutHash = window.location.href.split("#")[0];
        
        history.replaceState(null, null, urlWithoutHash);

        selectInternalAnnounce.textContent = "";

      } else {

        history.replaceState(null, null, this.value);

      }

      selectInternalContent.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      var selectInternalContentSelected = location.hash.slice(1);

      document.getElementById(selectInternalContentSelected).removeAttribute("hidden");

      // Set selected jump menu to active.

      selectInternal.forEach(function(menu) {

        menu.classList.remove(selectInternalState);

      });

      selectInternalParent.classList.add(selectInternalState);

    });

  });

  // Fix for some browsers not resetting the select index on page unload.

  window.addEventListener("beforeunload", function() {

    selectInternal.forEach(function(menu) {

      if (!menu.classList.contains(selectInternalState)) {

        menu.querySelector("select").selectedIndex = 0;

      }

    });

  });

})();

Dynamic Option Elements Anchor (Dynamic Option Elements)

California

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.

Abitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

New York

Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.

Pennsylvania

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante.

  • Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
  • Aliquam tincidunt mauris eu risus.
  • Vestibulum auctor dapibus neque.

Senectus et netus et malesuada fames ac turpis egestas ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Senectus et netus et fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Senectus et netus et malesuada egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

Experimental: Experimental examples or components may require additional work, further testing, and may not be fully supported or accessible. They should be carefully evaluated before being used in a production environment.

<div class="select-internal" data-dynamic>

    <nav aria-label="Job Locations" class="select-internal__nav">
  
      <label class="select-internal__label">Select your job location</label>
  
      <select class="select-internal__select">
  
      </select>

      <div class="visually-hidden" aria-live="polite"></div>
  
    </nav>
  
    <div class="select-internal__content" data-label="California">
  
      <h2>California</h2>
  
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, <a href="#">tempor sit amet</a>, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
  
      <p><strong>Abitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. <a href="#">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.</p>
  
    </div>
  
    <div class="select-internal__content" data-label="New York">
  
      <h2>New York</h2>
  
      <p>Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
  
    </div>
  
    <div class="select-internal__content" data-label="Pennsylvania">
  
      <h2>Pennsylvania</h2>
  
      <p>Pellentesque habitant <a href="#">morbi tristique senectus</a> et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante.</p>
  
      <ul>
        <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
        <li>Aliquam tincidunt mauris eu risus.</li>
        <li>Vestibulum auctor dapibus neque.</li>
      </ul>
  
      <p>Senectus et netus et malesuada fames ac turpis egestas ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Senectus et netus et fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Senectus et netus et malesuada egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
  
    </div>
  
  </div>
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

  Dependencies: Sass

*/

.select-internal {
  
  &__nav {
  background-color: #eee;
  border-radius: .5em;
  display: grid;
  gap: .5em;
  max-inline-size: calc(420rem / 16);
  padding: 1em;
  }
  
  &__label {
  font-weight: bold;
  margin: 0;
  }

  &__select {
  background-color: #FFF;
  border: 1px #ccc solid;
  font-size: inherit;
  padding: .5em;
  inline-size: 100%;
  }

  &__content {
  margin-block-start: 2em;
    
    &:target {
    scroll-margin-top: calc(190em / 16);
    }
  
  }

  // Custom Select 

  &[data-custom-select] {

    --select-primary-color: #6F00EF;
    --select-border-radius: calc(5rem / 16);

    .select-internal__select, ::picker(select) {

      appearance: base-select;
      line-height: normal;

    }

    .select-internal__select {
    border-radius: var(--select-border-radius);

      &:focus-visible {
      outline: calc(2rem / 16) var(--select-primary-color) solid;
      outline-offset: calc(2rem / 16);
      }

      &::picker-icon {
      color: var(--select-primary-color);
      transition: .4s rotate;
      }

      &:open::picker-icon {
      rotate: 180deg;
      }

      optgroup {
        
        option {
        margin-inline-start: 1rem;
        }

      }

      legend {
      color: var(--select-primary-color);
      margin-block: 1rem;
      }

      option {
      border-radius: var(--select-border-radius);
      margin-block-end: calc(8rem / 16);
      padding: calc(8rem / 16) calc(8rem / 16) calc(8rem / 16) 1rem;
      
        &::checkmark {
        border-radius: 100vw;
        border: calc(2rem / 16) #fff solid;
        color: #fff;
        font-weight: bold;
        margin-inline-start: auto;
        order: 1;
        padding: calc(3rem / 16) calc(8rem / 16);
        }

        &[value=""] {
        background-color: #eee;

          &:not(:hover):not(:focus) {

            &::checkmark {
            border-color: #000;
            color: #000;
            }

          }

        }

        &:focus, &:hover {
        outline: 0;
        color: #fff;
        background-color: var(--select-primary-color);
        }

      }

    }

    // This is the select dropdown

    ::picker(select) {
    border-radius: var(--select-border-radius);
    border: calc(1rem / 16) #666 solid;
    box-shadow: 0 calc(4rem / 16) calc(16rem / 16) rgb(0 0 0 / .8);
    margin: 1rem 1rem 0 0;
    padding: 1rem;
    scrollbar-color: var(--select-primary-color) transparent;
    scrollbar-width: thin;
    }

  }
  
}
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

*/

(function() {

  "use strict";

  // Display which component is in use via console:

  console.log("%cSelect Navigation (Internal)%cv1.8.0", "background: #2d2d2d; color: #fff; padding: 6px 10px; border-radius: 16px 0 0 16px; font-weight: 600;" , "background: #6e00ee; color: #fff; padding: 6px 10px; border-radius: 0 16px 16px 0; font-weight: 600;");

  var selectInternalClass = ".select-internal";
  var selectInternalLabelClass = ".select-internal__label";
  var selectInternalSelectClass = ".select-internal__select";
  var selectInternalOptionClass = ".select-internal__select option";
  var selectInternalContentClass = ".select-internal__content";
  var selectInternalDataCustomAriaLive = "data-aria-live";
  var selectInternal = document.querySelectorAll(selectInternalClass);
  var selectInternalLabel = document.querySelectorAll(selectInternalLabelClass);
  var selectInternalSelect = document.querySelectorAll(selectInternalSelectClass);
  var selectInternalState = "active";
  var selectInternalContentList = [];

  // On page load

  selectInternal.forEach(function(component) {

    // Check if "dynamic" Jump Menu is in use.

    if (component.hasAttribute("data-dynamic")) {

      var selectInternalContent = component.querySelectorAll(selectInternalContentClass);
      var selectInternalContentNth = component.querySelectorAll(selectInternalContentClass + ":nth-of-type(n + 2)");

      selectInternalContentNth.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      selectInternalContent.forEach(function(content, i) {

        var count = i + 1;

        // If custom ID present

        var contentID = content.hasAttribute("data-id") ? content.getAttribute("data-id"): "content-" + count;

        content.setAttribute("id", contentID);

        // Create option element

        var option = document.createElement("option");

        option.setAttribute("value", "#" + contentID);
        option.textContent = content.getAttribute("data-label");

        // Append each dynamic option.

        component.querySelector("select").appendChild(option);

      });

    }

  });

  var selectInternalOption = document.querySelectorAll(selectInternalOptionClass);

  selectInternalLabel.forEach(function(label, e) {

    // Apply "for" attribute to each label.

    label.setAttribute("for", "select-internal-" + (e + 1));

  });

  selectInternalSelect.forEach(function(select, e) {

    // Apply "id" to each select.

    select.setAttribute("id", "select-internal-" + (e + 1));

  });

  // Get all Job Menu options on page and push to array.

  selectInternalOption.forEach(function(option) {

    selectInternalContentList.push(option.getAttribute("value"));

  });

  function selectInternalSelectedState() {

    var selectInternalHash = location.hash || selectInternalContentList[0];

    if (!selectInternalHash) {

      return;
    
    }

    var selectInternalFragment = selectInternalHash.slice(1);

    // Check array against hash

    if (selectInternalContentList.includes(selectInternalHash)) {

      // If hash matches one of the array selections, load the selected content in hash
    
      var selectInternalSelected = document.getElementById(selectInternalFragment);
      var selectInternalContent = selectInternalSelected.closest(selectInternalClass).querySelectorAll(selectInternalContentClass);

      selectInternalContent.forEach(function(content) {
      
        content.setAttribute("hidden", "");

      });

      selectInternalSelected.removeAttribute("hidden");

      selectInternalOption.forEach(function(option) {

        var optionValue = option.getAttribute("value");

        if (location.hash === optionValue) {

          option.setAttribute("selected", "");
          option.closest(selectInternalClass).classList.add(selectInternalState);

        } else {

          option.removeAttribute("selected");

        }

      });

      // Update select dropdown

      var select = document.querySelector(selectInternalClass + " select");

      if (select) {

        select.value = selectInternalHash;

      }

    }

  }

  selectInternalSelectedState();

  // Hash change event listener
  
  window.addEventListener("hashchange", function() {

    selectInternalSelectedState();

    // When link is pressed, place programatic focus on selected content. This is useful if links are elsewhere on the page.
    // If this causes issues elsewhere on page when haschange is fired, let me know.

    var selectedContent = document.querySelector(selectInternalContentClass + ":not([hidden])");
    var selectedContentID = selectedContent.getAttribute("id");
    var URLHash = location.hash.slice(1);

    if(URLHash === selectedContentID) {

      selectedContent.setAttribute("tabindex", "-1");
      selectedContent.focus();

    }

  });

  selectInternalSelect.forEach(function(select) {

    select.addEventListener("change", function() {

      var selectInternalParent = this.closest(selectInternalClass);
      var selectInternalContent = selectInternalParent.querySelectorAll(selectInternalContentClass);

      // Send message to screen reader.

      var selectInternalAnnounce = selectInternalParent.querySelector("div[aria-live]");

      if(!selectInternalParent.hasAttribute(selectInternalDataCustomAriaLive)){

        selectInternalAnnounce.textContent = "Selected Content: " + this.options[this.selectedIndex].text; // TODO: Tokenize for i18n.

      }

      // Update hash in URL

      if (this.value === "") {

        var urlWithoutHash = window.location.href.split("#")[0];
        
        history.replaceState(null, null, urlWithoutHash);

        selectInternalAnnounce.textContent = "";

      } else {

        history.replaceState(null, null, this.value);

      }

      selectInternalContent.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      var selectInternalContentSelected = location.hash.slice(1);

      document.getElementById(selectInternalContentSelected).removeAttribute("hidden");

      // Set selected jump menu to active.

      selectInternal.forEach(function(menu) {

        menu.classList.remove(selectInternalState);

      });

      selectInternalParent.classList.add(selectInternalState);

    });

  });

  // Fix for some browsers not resetting the select index on page unload.

  window.addEventListener("beforeunload", function() {

    selectInternal.forEach(function(menu) {

      if (!menu.classList.contains(selectInternalState)) {

        menu.querySelector("select").selectedIndex = 0;

      }

    });

  });

})();

Select with Placeholder Anchor (Select with Placeholder)

<div class="select-internal">

  <nav aria-label="Preferred Job Position" class="select-internal__nav">

    <label class="select-internal__label">Select your preferred job position</label>

    <select class="select-internal__select">
        <option value>Please Select</option>
        <option value="#ceo">CEO</option>
        <option value="#silly-walks">Minister of Silly Walks</option>
        <option value="#director-ui-ux">Director, Global UI & UX Delivery</option>
    </select>

    <div class="visually-hidden" aria-live="polite"></div>

  </nav>

  <div class="select-internal__content" hidden id="ceo">

    <h2>CEO</h2>

    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, <a href="#!">tempor sit amet</a>, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>

  </div>

  <div class="select-internal__content" hidden id="silly-walks">

    <h2>Minister of Silly Walks</h2>

    <p>Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>

  </div>

  <div class="select-internal__content" hidden id="director-ui-ux">

    <h2>Director, Global UI & UX Delivery</h2>

    <p>Pellentesque habitant et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante.</p>

    <ul>
      <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
      <li>Aliquam tincidunt mauris eu risus.</li>
      <li>Vestibulum auctor dapibus neque.</li>
    </ul>

  </div>

</div>
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

  Dependencies: Sass

*/

.select-internal {
  
  &__nav {
  background-color: #eee;
  border-radius: .5em;
  display: grid;
  gap: .5em;
  max-inline-size: calc(420rem / 16);
  padding: 1em;
  }
  
  &__label {
  font-weight: bold;
  margin: 0;
  }

  &__select {
  background-color: #FFF;
  border: 1px #ccc solid;
  font-size: inherit;
  padding: .5em;
  inline-size: 100%;
  }

  &__content {
  margin-block-start: 2em;
    
    &:target {
    scroll-margin-top: calc(190em / 16);
    }
  
  }

  // Custom Select 

  &[data-custom-select] {

    --select-primary-color: #6F00EF;
    --select-border-radius: calc(5rem / 16);

    .select-internal__select, ::picker(select) {

      appearance: base-select;
      line-height: normal;

    }

    .select-internal__select {
    border-radius: var(--select-border-radius);

      &:focus-visible {
      outline: calc(2rem / 16) var(--select-primary-color) solid;
      outline-offset: calc(2rem / 16);
      }

      &::picker-icon {
      color: var(--select-primary-color);
      transition: .4s rotate;
      }

      &:open::picker-icon {
      rotate: 180deg;
      }

      optgroup {
        
        option {
        margin-inline-start: 1rem;
        }

      }

      legend {
      color: var(--select-primary-color);
      margin-block: 1rem;
      }

      option {
      border-radius: var(--select-border-radius);
      margin-block-end: calc(8rem / 16);
      padding: calc(8rem / 16) calc(8rem / 16) calc(8rem / 16) 1rem;
      
        &::checkmark {
        border-radius: 100vw;
        border: calc(2rem / 16) #fff solid;
        color: #fff;
        font-weight: bold;
        margin-inline-start: auto;
        order: 1;
        padding: calc(3rem / 16) calc(8rem / 16);
        }

        &[value=""] {
        background-color: #eee;

          &:not(:hover):not(:focus) {

            &::checkmark {
            border-color: #000;
            color: #000;
            }

          }

        }

        &:focus, &:hover {
        outline: 0;
        color: #fff;
        background-color: var(--select-primary-color);
        }

      }

    }

    // This is the select dropdown

    ::picker(select) {
    border-radius: var(--select-border-radius);
    border: calc(1rem / 16) #666 solid;
    box-shadow: 0 calc(4rem / 16) calc(16rem / 16) rgb(0 0 0 / .8);
    margin: 1rem 1rem 0 0;
    padding: 1rem;
    scrollbar-color: var(--select-primary-color) transparent;
    scrollbar-width: thin;
    }

  }
  
}
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

*/

(function() {

  "use strict";

  // Display which component is in use via console:

  console.log("%cSelect Navigation (Internal)%cv1.8.0", "background: #2d2d2d; color: #fff; padding: 6px 10px; border-radius: 16px 0 0 16px; font-weight: 600;" , "background: #6e00ee; color: #fff; padding: 6px 10px; border-radius: 0 16px 16px 0; font-weight: 600;");

  var selectInternalClass = ".select-internal";
  var selectInternalLabelClass = ".select-internal__label";
  var selectInternalSelectClass = ".select-internal__select";
  var selectInternalOptionClass = ".select-internal__select option";
  var selectInternalContentClass = ".select-internal__content";
  var selectInternalDataCustomAriaLive = "data-aria-live";
  var selectInternal = document.querySelectorAll(selectInternalClass);
  var selectInternalLabel = document.querySelectorAll(selectInternalLabelClass);
  var selectInternalSelect = document.querySelectorAll(selectInternalSelectClass);
  var selectInternalState = "active";
  var selectInternalContentList = [];

  // On page load

  selectInternal.forEach(function(component) {

    // Check if "dynamic" Jump Menu is in use.

    if (component.hasAttribute("data-dynamic")) {

      var selectInternalContent = component.querySelectorAll(selectInternalContentClass);
      var selectInternalContentNth = component.querySelectorAll(selectInternalContentClass + ":nth-of-type(n + 2)");

      selectInternalContentNth.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      selectInternalContent.forEach(function(content, i) {

        var count = i + 1;

        // If custom ID present

        var contentID = content.hasAttribute("data-id") ? content.getAttribute("data-id"): "content-" + count;

        content.setAttribute("id", contentID);

        // Create option element

        var option = document.createElement("option");

        option.setAttribute("value", "#" + contentID);
        option.textContent = content.getAttribute("data-label");

        // Append each dynamic option.

        component.querySelector("select").appendChild(option);

      });

    }

  });

  var selectInternalOption = document.querySelectorAll(selectInternalOptionClass);

  selectInternalLabel.forEach(function(label, e) {

    // Apply "for" attribute to each label.

    label.setAttribute("for", "select-internal-" + (e + 1));

  });

  selectInternalSelect.forEach(function(select, e) {

    // Apply "id" to each select.

    select.setAttribute("id", "select-internal-" + (e + 1));

  });

  // Get all Job Menu options on page and push to array.

  selectInternalOption.forEach(function(option) {

    selectInternalContentList.push(option.getAttribute("value"));

  });

  function selectInternalSelectedState() {

    var selectInternalHash = location.hash || selectInternalContentList[0];

    if (!selectInternalHash) {

      return;
    
    }

    var selectInternalFragment = selectInternalHash.slice(1);

    // Check array against hash

    if (selectInternalContentList.includes(selectInternalHash)) {

      // If hash matches one of the array selections, load the selected content in hash
    
      var selectInternalSelected = document.getElementById(selectInternalFragment);
      var selectInternalContent = selectInternalSelected.closest(selectInternalClass).querySelectorAll(selectInternalContentClass);

      selectInternalContent.forEach(function(content) {
      
        content.setAttribute("hidden", "");

      });

      selectInternalSelected.removeAttribute("hidden");

      selectInternalOption.forEach(function(option) {

        var optionValue = option.getAttribute("value");

        if (location.hash === optionValue) {

          option.setAttribute("selected", "");
          option.closest(selectInternalClass).classList.add(selectInternalState);

        } else {

          option.removeAttribute("selected");

        }

      });

      // Update select dropdown

      var select = document.querySelector(selectInternalClass + " select");

      if (select) {

        select.value = selectInternalHash;

      }

    }

  }

  selectInternalSelectedState();

  // Hash change event listener
  
  window.addEventListener("hashchange", function() {

    selectInternalSelectedState();

    // When link is pressed, place programatic focus on selected content. This is useful if links are elsewhere on the page.
    // If this causes issues elsewhere on page when haschange is fired, let me know.

    var selectedContent = document.querySelector(selectInternalContentClass + ":not([hidden])");
    var selectedContentID = selectedContent.getAttribute("id");
    var URLHash = location.hash.slice(1);

    if(URLHash === selectedContentID) {

      selectedContent.setAttribute("tabindex", "-1");
      selectedContent.focus();

    }

  });

  selectInternalSelect.forEach(function(select) {

    select.addEventListener("change", function() {

      var selectInternalParent = this.closest(selectInternalClass);
      var selectInternalContent = selectInternalParent.querySelectorAll(selectInternalContentClass);

      // Send message to screen reader.

      var selectInternalAnnounce = selectInternalParent.querySelector("div[aria-live]");

      if(!selectInternalParent.hasAttribute(selectInternalDataCustomAriaLive)){

        selectInternalAnnounce.textContent = "Selected Content: " + this.options[this.selectedIndex].text; // TODO: Tokenize for i18n.

      }

      // Update hash in URL

      if (this.value === "") {

        var urlWithoutHash = window.location.href.split("#")[0];
        
        history.replaceState(null, null, urlWithoutHash);

        selectInternalAnnounce.textContent = "";

      } else {

        history.replaceState(null, null, this.value);

      }

      selectInternalContent.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      var selectInternalContentSelected = location.hash.slice(1);

      document.getElementById(selectInternalContentSelected).removeAttribute("hidden");

      // Set selected jump menu to active.

      selectInternal.forEach(function(menu) {

        menu.classList.remove(selectInternalState);

      });

      selectInternalParent.classList.add(selectInternalState);

    });

  });

  // Fix for some browsers not resetting the select index on page unload.

  window.addEventListener("beforeunload", function() {

    selectInternal.forEach(function(menu) {

      if (!menu.classList.contains(selectInternalState)) {

        menu.querySelector("select").selectedIndex = 0;

      }

    });

  });

})();

Select with Option Group Anchor (Select with Option Group)

<div class="select-internal">

  <nav aria-label="Fancy Cars" class="select-internal__nav">

    <label class="select-internal__label">Select your vehicle</label>

    <select class="select-internal__select">
      <option value>Please Select</option>
      <optgroup label="Electric Cars">
        <option disabled value="#tesla-model-s">Tesla Model S</option>
        <option value="#lucid-air">Lucid Air</option>
        <option value="#nissan-leaf">Nissan Leaf</option>
      </optgroup>
      <optgroup label="Luxury Cars">
        <option value="#bmw-7series">BMW 7 Series</option>
      </optgroup>
      <optgroup label="Sports Cars">
        <option value="#ferrari-roma">Ferrari Roma</option>
      </optgroup>
    </select>

    <div class="visually-hidden" aria-live="polite"></div> 

  </nav>

  <div class="select-internal__content" hidden id="lucid-air">

    <h2>Lucid Air</h2>

    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, <a href="#!">tempor sit amet</a>, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>

  </div>

  <div class="select-internal__content" hidden id="nissan-leaf">

    <h2>Nissan Leaf</h2>

    <p>Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>

  </div>

  <div class="select-internal__content" hidden id="bmw-7series">

    <h2>BMW 7 Series</h2>

    <p>Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>

  </div>

  <div class="select-internal__content" hidden id="ferrari-roma">

    <h2>Ferrari Roma</h2>

    <p>Pellentesque habitant et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante.</p>

    <ul>
      <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
      <li>Aliquam tincidunt mauris eu risus.</li>
      <li>Vestibulum auctor dapibus neque.</li>
    </ul>

  </div>

</div>
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

  Dependencies: Sass

*/

.select-internal {
  
  &__nav {
  background-color: #eee;
  border-radius: .5em;
  display: grid;
  gap: .5em;
  max-inline-size: calc(420rem / 16);
  padding: 1em;
  }
  
  &__label {
  font-weight: bold;
  margin: 0;
  }

  &__select {
  background-color: #FFF;
  border: 1px #ccc solid;
  font-size: inherit;
  padding: .5em;
  inline-size: 100%;
  }

  &__content {
  margin-block-start: 2em;
    
    &:target {
    scroll-margin-top: calc(190em / 16);
    }
  
  }

  // Custom Select 

  &[data-custom-select] {

    --select-primary-color: #6F00EF;
    --select-border-radius: calc(5rem / 16);

    .select-internal__select, ::picker(select) {

      appearance: base-select;
      line-height: normal;

    }

    .select-internal__select {
    border-radius: var(--select-border-radius);

      &:focus-visible {
      outline: calc(2rem / 16) var(--select-primary-color) solid;
      outline-offset: calc(2rem / 16);
      }

      &::picker-icon {
      color: var(--select-primary-color);
      transition: .4s rotate;
      }

      &:open::picker-icon {
      rotate: 180deg;
      }

      optgroup {
        
        option {
        margin-inline-start: 1rem;
        }

      }

      legend {
      color: var(--select-primary-color);
      margin-block: 1rem;
      }

      option {
      border-radius: var(--select-border-radius);
      margin-block-end: calc(8rem / 16);
      padding: calc(8rem / 16) calc(8rem / 16) calc(8rem / 16) 1rem;
      
        &::checkmark {
        border-radius: 100vw;
        border: calc(2rem / 16) #fff solid;
        color: #fff;
        font-weight: bold;
        margin-inline-start: auto;
        order: 1;
        padding: calc(3rem / 16) calc(8rem / 16);
        }

        &[value=""] {
        background-color: #eee;

          &:not(:hover):not(:focus) {

            &::checkmark {
            border-color: #000;
            color: #000;
            }

          }

        }

        &:focus, &:hover {
        outline: 0;
        color: #fff;
        background-color: var(--select-primary-color);
        }

      }

    }

    // This is the select dropdown

    ::picker(select) {
    border-radius: var(--select-border-radius);
    border: calc(1rem / 16) #666 solid;
    box-shadow: 0 calc(4rem / 16) calc(16rem / 16) rgb(0 0 0 / .8);
    margin: 1rem 1rem 0 0;
    padding: 1rem;
    scrollbar-color: var(--select-primary-color) transparent;
    scrollbar-width: thin;
    }

  }
  
}
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

*/

(function() {

  "use strict";

  // Display which component is in use via console:

  console.log("%cSelect Navigation (Internal)%cv1.8.0", "background: #2d2d2d; color: #fff; padding: 6px 10px; border-radius: 16px 0 0 16px; font-weight: 600;" , "background: #6e00ee; color: #fff; padding: 6px 10px; border-radius: 0 16px 16px 0; font-weight: 600;");

  var selectInternalClass = ".select-internal";
  var selectInternalLabelClass = ".select-internal__label";
  var selectInternalSelectClass = ".select-internal__select";
  var selectInternalOptionClass = ".select-internal__select option";
  var selectInternalContentClass = ".select-internal__content";
  var selectInternalDataCustomAriaLive = "data-aria-live";
  var selectInternal = document.querySelectorAll(selectInternalClass);
  var selectInternalLabel = document.querySelectorAll(selectInternalLabelClass);
  var selectInternalSelect = document.querySelectorAll(selectInternalSelectClass);
  var selectInternalState = "active";
  var selectInternalContentList = [];

  // On page load

  selectInternal.forEach(function(component) {

    // Check if "dynamic" Jump Menu is in use.

    if (component.hasAttribute("data-dynamic")) {

      var selectInternalContent = component.querySelectorAll(selectInternalContentClass);
      var selectInternalContentNth = component.querySelectorAll(selectInternalContentClass + ":nth-of-type(n + 2)");

      selectInternalContentNth.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      selectInternalContent.forEach(function(content, i) {

        var count = i + 1;

        // If custom ID present

        var contentID = content.hasAttribute("data-id") ? content.getAttribute("data-id"): "content-" + count;

        content.setAttribute("id", contentID);

        // Create option element

        var option = document.createElement("option");

        option.setAttribute("value", "#" + contentID);
        option.textContent = content.getAttribute("data-label");

        // Append each dynamic option.

        component.querySelector("select").appendChild(option);

      });

    }

  });

  var selectInternalOption = document.querySelectorAll(selectInternalOptionClass);

  selectInternalLabel.forEach(function(label, e) {

    // Apply "for" attribute to each label.

    label.setAttribute("for", "select-internal-" + (e + 1));

  });

  selectInternalSelect.forEach(function(select, e) {

    // Apply "id" to each select.

    select.setAttribute("id", "select-internal-" + (e + 1));

  });

  // Get all Job Menu options on page and push to array.

  selectInternalOption.forEach(function(option) {

    selectInternalContentList.push(option.getAttribute("value"));

  });

  function selectInternalSelectedState() {

    var selectInternalHash = location.hash || selectInternalContentList[0];

    if (!selectInternalHash) {

      return;
    
    }

    var selectInternalFragment = selectInternalHash.slice(1);

    // Check array against hash

    if (selectInternalContentList.includes(selectInternalHash)) {

      // If hash matches one of the array selections, load the selected content in hash
    
      var selectInternalSelected = document.getElementById(selectInternalFragment);
      var selectInternalContent = selectInternalSelected.closest(selectInternalClass).querySelectorAll(selectInternalContentClass);

      selectInternalContent.forEach(function(content) {
      
        content.setAttribute("hidden", "");

      });

      selectInternalSelected.removeAttribute("hidden");

      selectInternalOption.forEach(function(option) {

        var optionValue = option.getAttribute("value");

        if (location.hash === optionValue) {

          option.setAttribute("selected", "");
          option.closest(selectInternalClass).classList.add(selectInternalState);

        } else {

          option.removeAttribute("selected");

        }

      });

      // Update select dropdown

      var select = document.querySelector(selectInternalClass + " select");

      if (select) {

        select.value = selectInternalHash;

      }

    }

  }

  selectInternalSelectedState();

  // Hash change event listener
  
  window.addEventListener("hashchange", function() {

    selectInternalSelectedState();

    // When link is pressed, place programatic focus on selected content. This is useful if links are elsewhere on the page.
    // If this causes issues elsewhere on page when haschange is fired, let me know.

    var selectedContent = document.querySelector(selectInternalContentClass + ":not([hidden])");
    var selectedContentID = selectedContent.getAttribute("id");
    var URLHash = location.hash.slice(1);

    if(URLHash === selectedContentID) {

      selectedContent.setAttribute("tabindex", "-1");
      selectedContent.focus();

    }

  });

  selectInternalSelect.forEach(function(select) {

    select.addEventListener("change", function() {

      var selectInternalParent = this.closest(selectInternalClass);
      var selectInternalContent = selectInternalParent.querySelectorAll(selectInternalContentClass);

      // Send message to screen reader.

      var selectInternalAnnounce = selectInternalParent.querySelector("div[aria-live]");

      if(!selectInternalParent.hasAttribute(selectInternalDataCustomAriaLive)){

        selectInternalAnnounce.textContent = "Selected Content: " + this.options[this.selectedIndex].text; // TODO: Tokenize for i18n.

      }

      // Update hash in URL

      if (this.value === "") {

        var urlWithoutHash = window.location.href.split("#")[0];
        
        history.replaceState(null, null, urlWithoutHash);

        selectInternalAnnounce.textContent = "";

      } else {

        history.replaceState(null, null, this.value);

      }

      selectInternalContent.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      var selectInternalContentSelected = location.hash.slice(1);

      document.getElementById(selectInternalContentSelected).removeAttribute("hidden");

      // Set selected jump menu to active.

      selectInternal.forEach(function(menu) {

        menu.classList.remove(selectInternalState);

      });

      selectInternalParent.classList.add(selectInternalState);

    });

  });

  // Fix for some browsers not resetting the select index on page unload.

  window.addEventListener("beforeunload", function() {

    selectInternal.forEach(function(menu) {

      if (!menu.classList.contains(selectInternalState)) {

        menu.querySelector("select").selectedIndex = 0;

      }

    });

  });

})();

Select with Option Group (Customized Select Element) Anchor (Select with Option Group (Customized Select Element))

Experimental: Experimental examples or components may require additional work, further testing, and may not be fully supported or accessible. They should be carefully evaluated before being used in a production environment.

<div class="select-internal" data-custom-select>

  <nav aria-label="Movies" class="select-internal__nav">

    <label class="select-internal__label">Select your movie</label>

    <select class="select-internal__select">
        <button>
            <selectedcontent></selectedcontent>
        </button>
        <option value>Please Select</option>
        <optgroup label="Action">
            <legend>Action</legend>
            <div>
                <option value="#mad-max-fury-road">Mad Max: Fury Road</option>
                <option value="#john-wick">John Wick</option>
                <option value="#the-dark-knight">The Dark Knight</option>
            </div>
        </optgroup>
        <optgroup label="Comedy">
            <legend>Comedy</legend>
            <div>
                <option value="#superbad">Superbad</option>
                <option value="#step-brothers">Step Brothers</option>
            </div>
        </optgroup>
        <optgroup label="Drama">
            <legend>Drama</legend>
            <div>
                <option value="#shawshank-redemption">The Shawshank Redemption</option>
                <option value="#forrest-gump">Forrest Gump</option>
            </div>
        </optgroup>
        <optgroup label="Science Fiction">
            <legend>Science Fiction</legend>
            <div>
                <option value="#interstellar">Interstellar</option>
                <option value="#blade-runner-2049">Blade Runner 2049</option>
            </div>
        </optgroup>
    </select>

    <div class="visually-hidden" aria-live="polite"></div> 

  </nav>

    <div class="select-internal__content" hidden id="mad-max-fury-road">

        <h2>Mad Max: Fury Road</h2>
    
        <p>A high-octane post-apocalyptic action film filled with relentless chases, practical effects, and minimal dialogue, centered on survival in a desert wasteland.</p>
    
    </div>

    <div class="select-internal__content" hidden id="john-wick">
    
        <h2>John Wick</h2>
    
        <p>A sleek, stylized action thriller following a retired hitman seeking vengeance, known for its precise choreography and world-building within an underground assassin society.</p>
    
    </div>

    <div class="select-internal__content" hidden id="the-dark-knight">
    
        <h2>The Dark Knight</h2>
    
        <p>A gritty superhero crime drama exploring chaos and morality, featuring an iconic performance of the Joker and complex themes of justice and sacrifice.</p>
    
    </div>

    <div class="select-internal__content" hidden id="superbad">
    
        <h2>Superbad</h2>
    
        <p>A coming-of-age comedy that follows two friends navigating one wild night before graduation, packed with awkward humor and memorable characters.</p>
    
    </div>

    <div class="select-internal__content" hidden id="step-brothers">
    
        <h2>Step Brothers</h2>
    
        <p>A ridiculous and irreverent comedy about two grown men forced to live together as siblings, leading to absurd conflicts and unexpected bonding.</p>
    
    </div>

    <div class="select-internal__content" hidden id="shawshank-redemption">
    
        <h2>The Shawshank Redemption</h2>
    
        <p>A powerful drama about hope and resilience, following a man wrongfully imprisoned and his enduring friendship inside a harsh prison system.</p>
    
    </div>

    <div class="select-internal__content" hidden id="forrest-gump">
    
        <h2>Forrest Gump</h2>
    
        <p>A heartfelt drama chronicling the extraordinary life of an ordinary man, weaving through major historical events with sincerity and charm.</p>
    
    </div>

    <div class="select-internal__content" hidden id="interstellar">
    
        <h2>Interstellar</h2>
    
        <p>A visually stunning science fiction epic exploring space travel, time dilation, and human survival as a team ventures beyond our galaxy.</p>
    
    </div>

    <div class="select-internal__content" hidden id="blade-runner-2049">
    
        <h2>Blade Runner 2049</h2>
    
        <p>A contemplative sci-fi sequel that blends stunning visuals with philosophical questions about identity, memory, and what it means to be human.</p>
    
    </div>

</div>
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

  Dependencies: Sass

*/

.select-internal {
  
  &__nav {
  background-color: #eee;
  border-radius: .5em;
  display: grid;
  gap: .5em;
  max-inline-size: calc(420rem / 16);
  padding: 1em;
  }
  
  &__label {
  font-weight: bold;
  margin: 0;
  }

  &__select {
  background-color: #FFF;
  border: 1px #ccc solid;
  font-size: inherit;
  padding: .5em;
  inline-size: 100%;
  }

  &__content {
  margin-block-start: 2em;
    
    &:target {
    scroll-margin-top: calc(190em / 16);
    }
  
  }

  // Custom Select 

  &[data-custom-select] {

    --select-primary-color: #6F00EF;
    --select-border-radius: calc(5rem / 16);

    .select-internal__select, ::picker(select) {

      appearance: base-select;
      line-height: normal;

    }

    .select-internal__select {
    border-radius: var(--select-border-radius);

      &:focus-visible {
      outline: calc(2rem / 16) var(--select-primary-color) solid;
      outline-offset: calc(2rem / 16);
      }

      &::picker-icon {
      color: var(--select-primary-color);
      transition: .4s rotate;
      }

      &:open::picker-icon {
      rotate: 180deg;
      }

      optgroup {
        
        option {
        margin-inline-start: 1rem;
        }

      }

      legend {
      color: var(--select-primary-color);
      margin-block: 1rem;
      }

      option {
      border-radius: var(--select-border-radius);
      margin-block-end: calc(8rem / 16);
      padding: calc(8rem / 16) calc(8rem / 16) calc(8rem / 16) 1rem;
      
        &::checkmark {
        border-radius: 100vw;
        border: calc(2rem / 16) #fff solid;
        color: #fff;
        font-weight: bold;
        margin-inline-start: auto;
        order: 1;
        padding: calc(3rem / 16) calc(8rem / 16);
        }

        &[value=""] {
        background-color: #eee;

          &:not(:hover):not(:focus) {

            &::checkmark {
            border-color: #000;
            color: #000;
            }

          }

        }

        &:focus, &:hover {
        outline: 0;
        color: #fff;
        background-color: var(--select-primary-color);
        }

      }

    }

    // This is the select dropdown

    ::picker(select) {
    border-radius: var(--select-border-radius);
    border: calc(1rem / 16) #666 solid;
    box-shadow: 0 calc(4rem / 16) calc(16rem / 16) rgb(0 0 0 / .8);
    margin: 1rem 1rem 0 0;
    padding: 1rem;
    scrollbar-color: var(--select-primary-color) transparent;
    scrollbar-width: thin;
    }

  }
  
}
/*!

  Radancy Component Library: Select Navigation (Internal)

  Contributor(s):
  Michael "Spell" Spellacy

*/

(function() {

  "use strict";

  // Display which component is in use via console:

  console.log("%cSelect Navigation (Internal)%cv1.8.0", "background: #2d2d2d; color: #fff; padding: 6px 10px; border-radius: 16px 0 0 16px; font-weight: 600;" , "background: #6e00ee; color: #fff; padding: 6px 10px; border-radius: 0 16px 16px 0; font-weight: 600;");

  var selectInternalClass = ".select-internal";
  var selectInternalLabelClass = ".select-internal__label";
  var selectInternalSelectClass = ".select-internal__select";
  var selectInternalOptionClass = ".select-internal__select option";
  var selectInternalContentClass = ".select-internal__content";
  var selectInternalDataCustomAriaLive = "data-aria-live";
  var selectInternal = document.querySelectorAll(selectInternalClass);
  var selectInternalLabel = document.querySelectorAll(selectInternalLabelClass);
  var selectInternalSelect = document.querySelectorAll(selectInternalSelectClass);
  var selectInternalState = "active";
  var selectInternalContentList = [];

  // On page load

  selectInternal.forEach(function(component) {

    // Check if "dynamic" Jump Menu is in use.

    if (component.hasAttribute("data-dynamic")) {

      var selectInternalContent = component.querySelectorAll(selectInternalContentClass);
      var selectInternalContentNth = component.querySelectorAll(selectInternalContentClass + ":nth-of-type(n + 2)");

      selectInternalContentNth.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      selectInternalContent.forEach(function(content, i) {

        var count = i + 1;

        // If custom ID present

        var contentID = content.hasAttribute("data-id") ? content.getAttribute("data-id"): "content-" + count;

        content.setAttribute("id", contentID);

        // Create option element

        var option = document.createElement("option");

        option.setAttribute("value", "#" + contentID);
        option.textContent = content.getAttribute("data-label");

        // Append each dynamic option.

        component.querySelector("select").appendChild(option);

      });

    }

  });

  var selectInternalOption = document.querySelectorAll(selectInternalOptionClass);

  selectInternalLabel.forEach(function(label, e) {

    // Apply "for" attribute to each label.

    label.setAttribute("for", "select-internal-" + (e + 1));

  });

  selectInternalSelect.forEach(function(select, e) {

    // Apply "id" to each select.

    select.setAttribute("id", "select-internal-" + (e + 1));

  });

  // Get all Job Menu options on page and push to array.

  selectInternalOption.forEach(function(option) {

    selectInternalContentList.push(option.getAttribute("value"));

  });

  function selectInternalSelectedState() {

    var selectInternalHash = location.hash || selectInternalContentList[0];

    if (!selectInternalHash) {

      return;
    
    }

    var selectInternalFragment = selectInternalHash.slice(1);

    // Check array against hash

    if (selectInternalContentList.includes(selectInternalHash)) {

      // If hash matches one of the array selections, load the selected content in hash
    
      var selectInternalSelected = document.getElementById(selectInternalFragment);
      var selectInternalContent = selectInternalSelected.closest(selectInternalClass).querySelectorAll(selectInternalContentClass);

      selectInternalContent.forEach(function(content) {
      
        content.setAttribute("hidden", "");

      });

      selectInternalSelected.removeAttribute("hidden");

      selectInternalOption.forEach(function(option) {

        var optionValue = option.getAttribute("value");

        if (location.hash === optionValue) {

          option.setAttribute("selected", "");
          option.closest(selectInternalClass).classList.add(selectInternalState);

        } else {

          option.removeAttribute("selected");

        }

      });

      // Update select dropdown

      var select = document.querySelector(selectInternalClass + " select");

      if (select) {

        select.value = selectInternalHash;

      }

    }

  }

  selectInternalSelectedState();

  // Hash change event listener
  
  window.addEventListener("hashchange", function() {

    selectInternalSelectedState();

    // When link is pressed, place programatic focus on selected content. This is useful if links are elsewhere on the page.
    // If this causes issues elsewhere on page when haschange is fired, let me know.

    var selectedContent = document.querySelector(selectInternalContentClass + ":not([hidden])");
    var selectedContentID = selectedContent.getAttribute("id");
    var URLHash = location.hash.slice(1);

    if(URLHash === selectedContentID) {

      selectedContent.setAttribute("tabindex", "-1");
      selectedContent.focus();

    }

  });

  selectInternalSelect.forEach(function(select) {

    select.addEventListener("change", function() {

      var selectInternalParent = this.closest(selectInternalClass);
      var selectInternalContent = selectInternalParent.querySelectorAll(selectInternalContentClass);

      // Send message to screen reader.

      var selectInternalAnnounce = selectInternalParent.querySelector("div[aria-live]");

      if(!selectInternalParent.hasAttribute(selectInternalDataCustomAriaLive)){

        selectInternalAnnounce.textContent = "Selected Content: " + this.options[this.selectedIndex].text; // TODO: Tokenize for i18n.

      }

      // Update hash in URL

      if (this.value === "") {

        var urlWithoutHash = window.location.href.split("#")[0];
        
        history.replaceState(null, null, urlWithoutHash);

        selectInternalAnnounce.textContent = "";

      } else {

        history.replaceState(null, null, this.value);

      }

      selectInternalContent.forEach(function(content) {

        content.setAttribute("hidden", "");

      });

      var selectInternalContentSelected = location.hash.slice(1);

      document.getElementById(selectInternalContentSelected).removeAttribute("hidden");

      // Set selected jump menu to active.

      selectInternal.forEach(function(menu) {

        menu.classList.remove(selectInternalState);

      });

      selectInternalParent.classList.add(selectInternalState);

    });

  });

  // Fix for some browsers not resetting the select index on page unload.

  window.addEventListener("beforeunload", function() {

    selectInternal.forEach(function(menu) {

      if (!menu.classList.contains(selectInternalState)) {

        menu.querySelector("select").selectedIndex = 0;

      }

    });

  });

})();

Using Select Element for Navigation Anchor (Using Select Element for Navigation)

How we build components and the behaviors that they exhibit can have a serious impact on people with disabilities. Navigation components come in several different flavors. One such version of this is using the select element to navigate. By sticking to the following rules, we can ensure that this navigation type works well for everybody!

  1. All select menus must include a submit button. Unexpectedly taking a user to another page, without warning, will cause a change of context. This can be confusing to users and it is a WCAG failure.
  2. If you wish to navigate away from a page without a submit button, then use a hyperlink or a disclosure that reveals a list of hyperlinks to other pages.
  3. A select menu must always contain a label element. This label should include a note on anticipated behavior.
  4. The only exception to the above rules are select menus that change content within the page. Here, a submit button is not required. Please see Select Navigation (Internal) for more details.

Properties Anchor (Properties)

Use the following properties to configure this component.

ARIA Applies To Note Description
aria-label .select-internal__nav Mandatory
Used to pass a custom label to nav element. All menus must have a unique name describing them. Multiple menus on the page, should have a unique name.

Attribute Applies To Note Description
data-aria-live .select-internal Boolean, Optional
Used to suppress dynamic aria-live announcements. Here, you will be expected to wrap all of your .select-internal__content blocks with a single <div aria-live="polite"></div>. This technique should be used sparingly and only when each content area contains a minimal amount of content.
data-custom-select .select-internal Boolean, Optional
Used to allow custom styling of the select element and it's children. See Customizable Select Elements for more details.
data-dynamic .select-internal Boolean, Optional
Used in situations where you do not wish to hardcode the option element. The name of each option will be pulled from data-name.
data-id .select-internal__content String, Optional
Used with data-dynamic. This will provide a custom id value to each .select-internal__content container and a custom value to each option element. Custom values will override dynamically generated content-1, content-2, etc. Each custom value must be unique.
data-label .select-internal__content String, Mandatory
Used with data-dynamic. This will provide a custom value for any dynamically created option elements.

Class Applies To Note Description
.select-internal div, section Mandatory
Required on the parent element that wraps the menu and content.
.select-internal__nav nav Mandatory
Required on the nav element that wraps the label and select elements.
.select-internal__select select Mandatory
Required on the select element.
.select-internal__content div Mandatory
Required on each element that wraps individual content.

Release Notes Anchor (Release Notes)

Keep up to date on major changes to this component.

Feature
March 24, 2026: Added support for Customizable Select Elements.

Behavior
Select Menus should never be nested, nor is it supported.
Behavior
Removing the fragment from the URL is not supported. We want dynamically displayed content to be uniquely identified so that we can to link to and share it. The dynamic version of the menu will produce generic fragments (e.g., content-1, content-2, etc.).
Behavior
<div class="visually-hidden" aria-live="polite"></div> must always be included and be accessibly hidden.
Feature
The for and id attributes are generated via JavaScript to accomodate multiple Jump Menus per page. There is no need to manually add these attributes.

Feature
Include support for the optgroup element in Dynamic Setup.

Report Issues

Find a bug? Want a new feature? Report it on JIRA. You're so awesome!