Search code examples
htmlcss

Is there any way to make the expanded <details> element horizontally centered with its parent <summary> element?


I'm trying to use a <details> element to add a dropdown menu to my navbar, as it's a really nice and clean way of doing it without turning to JavaScript.

Everything works as intended, but I'd like to style the dropdown option(s) to have a little border (and thus padding) around them, as the text will otherwise be floating over my website content which would look off. When doing that, however, I run into the issue that the expanded <details> element always remains left-aligned with its parent <summary> element, meaning the dropdown items only expand towards the right and don't look very good.

Here's a minimal example:

.nav-item {
  padding: 10px;
}

.navbar-nav {
  display: flex;
}

.navbar-nav a {
  text-decoration: none;
}

.navbar-nav a:hover {
  color: #94add7;
}

.dropdownText:hover {
  color: #94add7;
}

.dropdownItem {
  /* display: none; */
  /* width: 100px; */
  position: absolute;
  margin-top: 10px;
  padding: 15px;
  border: 1px solid black;
}

.dropdownText {
  cursor: pointer;
}

.dropdownToggle details>summary {
  list-style: none;
}

.dropdownToggle details>summary::-webkit-details-marker {
  display: none;
}
<div class="navbar-nav">
  <div class="nav-item">
    <a class="nav-link">Link 1</a>
  </div>

  <div class="nav-item">
    <a class="nav-link">Link 2</a>
  </div>
  <div class="nav-item">
    <a class="nav-link">Link 3</a>
  </div>
  <div class="nav-item">●</div>
  <div class="nav-item">
    <div class="dropdownToggle">
      <details>
        <summary class="dropdownText">Dropdown Toggle</summary>
        <div class="dropdownItem">
          <a href="{targetUrl}">Dropdown Item with longer name</a>
        </div>
      </details>
    </div>
  </div>
</div>

Is there any way to make the <details> elements expand horizontally centered with the parent <summary> element when they have different widths?

Please note: I was previously using a <ul> instead of <div> elements for each navbar item, but after trying lots of things I considered the possibility that perhaps the <div> approach would make it easier to align them... to no avail so far. Meaning, I have no preference and I'm fine with either approach as long as it works.


Solution

  • Set .dropdownItem to left 50% and translateX(-50%) to center it.

    For that to work you need to set .dropdownToggle position to relative.

    See my EDIT comments in the css for specific edits.

    .nav-item {
      padding: 10px;
    }
    
    .navbar-nav {
      display: flex;
    }
    
    .navbar-nav a {
      text-decoration: none;
    }
    
    .navbar-nav a:hover {
      color: #94add7;
    }
    
    .dropdownText:hover {
      color: #94add7;
    }
    
    .dropdownItem {
      /* display: none; */
      /* width: 100px; */
      position: absolute;
      margin-top: 10px;
      padding: 15px;
      border: 1px solid black;
      
      /* EDIT Added */
      width: max-content;
      transform: translateX(-50%);
      left: 50%;
    }
    
    /* EDIT Added */
    .dropdownToggle {
      position: relative;
    }
    
    .dropdownText {
      cursor: pointer;
    }
    
    .dropdownToggle details>summary {
      list-style: none;
    }
    
    .dropdownToggle details>summary::-webkit-details-marker {
      display: none;
    }
    <div class="navbar-nav">
      <div class="nav-item">
        <a class="nav-link">Link 1</a>
      </div>
    
      <div class="nav-item">
        <a class="nav-link">Link 2</a>
      </div>
      <div class="nav-item">
        <a class="nav-link">Link 3</a>
      </div>
      <div class="nav-item">●</div>
      <div class="nav-item">
        <div class="dropdownToggle">
          <details>
            <summary class="dropdownText">Dropdown Toggle</summary>
            <div class="dropdownItem">
              <a href="{targetUrl}">Dropdown Item with longer name</a>
            </div>
          </details>
        </div>
      </div>
    </div>