Search code examples
htmlcssdropdownmultiple-columns

How to create a dropdown list with multiple adjacent 'columns'


I'm trying to write code for a shopping-website style dropdown that when one hovers over a target element on the navigation bar, it functions like the one depicted at this site.

I've spent two days on this, looking at so many pages, including previous postings on Stackoverflow, and tried what seems like an endless number of approaches, but I've simply not been able to crack this.

I should stress that I can already write the code for a dropdown that generates a single column of list of links when one hovers over the target element (that's easy); I'm really talking about aligned adjacent multiple columns.

A solution for a problem like this was posted here on Stackoverflow several years ago, but the person suggested the float method. I did actually try this, but the results were (very) unsatisfactory for my project.

If you can help me with this, to (instantly) see what my code looks like when rendered and painted, I've posted the necessary bits of code on Codepen, but the code is also posted below:

HTML:

.nav-list {
  list-style: none;
  border: 1px solid blue;
  display: flex;
  flex-flow: row wrap;
  align-items: left;
  justify-content: space-around;
  color: white;
  background-color: #429CD9;
}

#hire-dropdown {
  position: absolute;
  cursor: pointer;
  background-color: #429CD9;
}

.the-drop {
  display: none;
}

#hire-dropdown:hover>.the-drop {
  display: grid;
  grid-template-areas: "drop-1-list drop-2-list";
  grid-template-columns: 1fr 1fr;
}

.drop-1-list,
.drop-2-list {
  display: none;
}

.drop-1-list {
  grid-area: "drop-1-list";
}

.drop-2-list {
  grid-area: "drop-2-list";
}

.the-drop:hover>.drop-1-list,
.the-drop:hover>.drop-2-list {
  background-color: white;
  border: 1px solid black;
  list-style: none;
}
<nav>
  <ul class="nav-list">
    <li>Nothing</li>
    <li class="to-hire">
      <div id="hire-dropdown">To Hire
        <div class=".the-drop">
          <ul class="drop-1-list">
            <li><a href="#">Access</a></li>
            <li><a href="#">Breaking</a></li>
            <li><a href="#">Compaction</a></li>
            <li><a href="#">Cooling</a></li>
            <li><a href="#">Drilling</a></li>
            <li><a href="#">Lifting</a></li>
            <li><a href="#">Sanding</a></li>
            <li><a href="#">Sawing</a></li>
          </ul>
          <ul class="drop-2-list">
            <li><a href="#">Product 1</a></li>
            <li><a href="#">Product 2</a></li>
            <li><a href="#">Product 3</a></li>
            <li><a href="#">Product 4</a></li>
            <li><a href="#">Product 5</a></li>
          </ul>
        </div>

      </div>
    </li>
  </ul>
</nav>

If you also want to see the float method solution I referred to earlier, you can see it here (but I do not believe this is the right solution for my project).

Your (constructive) help would be most appreciated.


Solution

  • Not 100% sure how you want to handle all the narrow displays etc. but

    • <div class=".the-drop"> remove the period on the class in the markup
    • Remove some CSS - most of the time with CSS when you have issues remove some to get back to "basic" this work your way to your goal. I did that and adjusted some CSS selectors. No need for the absolute I think.
    • with the flex and then display of the blocks it jumps around a bit but I will leave that to you as to how you address that.

    .nav-list {
      list-style: none;
      border: 1px solid blue;
      display: flex;
      flex-flow: row wrap;
      align-items: start;
      justify-content: space-around;
      color: white;
      background-color: #429CD9;
    }
    
    #hire-dropdown {
      cursor: pointer;
      background-color: #429CD9;
    }
    
    .the-drop,
    .drop-1-list,
    .drop-2-list {
      display: none;
    }
    
    #hire-dropdown:hover * {
      display: grid;
    }
    
    #hire-dropdown .the-drop {
      grid-template-areas: "drop-1-list drop-2-list";
      grid-template-columns: 1fr 1fr;
    }
    
    .drop-1-list,
    .drop-2-list {
      background-color: white;
      border: 1px solid black;
      list-style: none;
    }
    
    .drop-1-list {
      grid-area: "drop-1-list";
    }
    
    .drop-2-list {
      grid-area: "drop-2-list";
    }
    <nav>
      <ul class="nav-list">
        <li>Nothing</li>
        <li class="to-hire">
          <div id="hire-dropdown">To Hire
            <div class="the-drop">
              <ul class="drop-1-list">
                <li><a href="#">Access</a></li>
                <li><a href="#">Breaking</a></li>
                <li><a href="#">Compaction</a></li>
                <li><a href="#">Cooling</a></li>
                <li><a href="#">Drilling</a></li>
                <li><a href="#">Lifting</a></li>
                <li><a href="#">Sanding</a></li>
                <li><a href="#">Sawing</a></li>
              </ul>
              <ul class="drop-2-list">
                <li><a href="#">Product 1</a></li>
                <li><a href="#">Product 2</a></li>
                <li><a href="#">Product 3</a></li>
                <li><a href="#">Product 4</a></li>
                <li><a href="#">Product 5</a></li>
              </ul>
            </div>
    
          </div>
        </li>
      </ul>
    </nav>