2

I'm trying to create a vertical dropdown menu that is positioned inside of div (.menu) where there are 6 words/divs or more (.dropdown) that when hovered over, slowly reveals a menu (.dropdown-content) that slides down from the div (.dropdown) that is hovered over and causes the next word/div (.dropdown) below to shift down in response to the menu (.dropdown-content) puching it down and then the menu and the div that was pushed recedes back to their original positions off hover.

Is this something that can even be done in HTML/CSS alone or would Javascript absolutely have to be used as this is for a school project and we are not allowed to use Javascript or anything but HTML & CSS.

.menu {
  position: relative;
  top: 0px;
  display: flex;
  flex-direction: column;
  width: 235px;
  height: auto;
  margin: auto;
  padding: auto;
  border-bottom-color: rgba(0, 5, 10, 1.00);
  background-color: rgba(0, 5, 10, 1.00);
  background-repeat: repeat;
  background-clip: content-box;
}

.dropbtn {
  /* style the buttons*/
  position: relative;
  background-color: rgba(40, 40, 40, 1.00);
  color: darkorange;
  padding: 10px;
  margin-left: 0px;
  font-size: 16px;
  border: none;
  border-radius: 5px;
  font-family: monospace;
  width: 235px;
}

.dropdown {
  /*initialize the revealing sliding menu*/
  position: absolute;
  margin: auto;
  padding: 10px;
  display: block;
}

.dropdown-menu {
  position: absolute;
  display: block;
  width: 100%;
  overflow: hidden;
}

.dropdown-menu .dropdown-content {
  display: block;
  margin-left: 0px;
  padding: 0px 0px 0px 0px;
  background-color: black;
  transform: translateY(-100%);
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  transition: transform 1.0s;
}

.dropdown-content a {
  display: block;
  color: white;
  padding: 12px 16px;
  text-decoration: none;
}

.dropdown-menu a:hover {
  background-color: darkorange;
  color: #000000;
}

.dropdown1:hover .dropdown-content {
  transform: translateY(0%);
}

.dropdown1:hover .dropdown-menu {
  position: absolute;
  transition: 0.3s;
  margin-bottom: 100px;
}

.dropdown1:hover .dropbtn {
  background-color: rgba(65, 65, 65, 1.00);
  color: white;
  transition: 0.3s;
}

.dropdown2:hover .dropdown-content {
  position: relative;
  transform: translateY(0%);
}

.dropdown2:hover .dropbtn {
  background-color: rgba(65, 65, 65, 1.00);
  color: white;
  transition: 0.3s;
}

.dropdown1 {
  position: relative;
}

.dropdown2 {
  position: relative;
}
<div class="menu">
  <div class="dropdown">
    <div class="dropdown1">
      <button class="dropbtn">DIV 1</button>
      <div class="dropdown-menu">
        <div class="dropdown-content">
          <a href="#">Link 1</a>
          <a href="#">Link 2</a>
          <a href="#">Link 3</a>
          <a href="#">Link 4</a>
          <a href="#">Link 5</a>
        </div>
      </div>
    </div>
    <div class="dropdown2">
      <button class="dropbtn">DIV 2</button>
      <div class="dropdown-menu">
        <div class="dropdown-content">
          <a href="#">Link 6</a>
          <a href="#">Link 7</a>
          <a href="#">Link 8</a>
          <a href="#">Link 9</a>
          <a href="#">Link 10</a>
        </div>
      </div>
    </div>
    <div class="dropdown2">
      <button class="dropbtn">DIV 3</button>
      <div class="dropdown-menu">
        <div class="dropdown-content">
          <a href="#">Link 11</a>
          <a href="#">Link 12</a>
          <a href="#">Link 13</a>
          <a href="#">Link 14</a>
          <a href="#">Link 15</a>
        </div>
      </div>
    </div>
  </div>
</div>
j08691
  • 204,283
  • 31
  • 260
  • 272
Guardic
  • 21
  • 1

1 Answers1

4

You can do that only with HTML and CSS, but unfortunately, it's not that pretty.

In this first example, I simplified the code and left just the essentials (I also changed some class names a bit): https://jsbin.com/jimufaw/edit?html,css,output

.menu {
  position: relative;
  top: 0px;
  display: flex;
  flex-direction: column;
  width: 235px;
  height: auto;
  margin: auto;
  padding: auto;
  border-bottom-color: rgba(0, 5, 10, 1.00);
  background-color: rgba(0, 5, 10, 1.00);
  background-repeat: repeat;
  background-clip: content-box;
}

.dropbtn {
  /* style the buttons*/
  position: relative;
  background-color: rgba(40, 40, 40, 1.00);
  color: darkorange;
  padding: 10px;
  margin-left: 0px;
  font-size: 16px;
  border: none;
  border-radius: 5px;
  font-family: monospace;
  width: 235px;
  transition: background 0.3s ease;
  cursor: pointer;
}

.dropdowns {
  /*initialize the revealing sliding menu*/
  margin: auto;
  display: block;
}

.dropdown-menu {
  overflow: hidden;
  height: 0;
}

.dropdown-menu .dropdown-content {
  display: block;
  background-color: black;
}

.dropdown-content a {
  display: block;
  color: white;
  padding: 12px 16px;
  text-decoration: none;
}

.dropdown-menu a:hover {
  background-color: darkorange;
  color: #000000;
}

.dropdown:hover .dropdown-menu {
  height: auto;
}

.dropdown:hover .dropbtn {
  background-color: rgba(65, 65, 65, 1.00);
  color: white;
}
<div class="menu">
  <div class="dropdowns">
    <div class="dropdown dropdown1">
      <button class="dropbtn">DIV 1</button>
      <div class="dropdown-menu">
        <div class="dropdown-content">
          <a href="#">Link 1</a>
          <a href="#">Link 2</a>
          <a href="#">Link 3</a>
          <a href="#">Link 4</a>
          <a href="#">Link 5</a>
        </div>
      </div>
    </div>
    <div class="dropdown dropdown2">
      <button class="dropbtn">DIV 2</button>
      <div class="dropdown-menu">
        <div class="dropdown-content">
          <a href="#">Link 6</a>
          <a href="#">Link 7</a>
          <a href="#">Link 8</a>
          <a href="#">Link 9</a>
          <a href="#">Link 10</a>
        </div>
      </div>
    </div>
    <div class="dropdown dropdown3">
      <button class="dropbtn">DIV 3</button>
      <div class="dropdown-menu">
        <div class="dropdown-content">
          <a href="#">Link 11</a>
          <a href="#">Link 12</a>
          <a href="#">Link 13</a>
          <a href="#">Link 14</a>
          <a href="#">Link 15</a>
        </div>
      </div>
    </div>
  </div>
</div>

Basically, if you want the divs to influence each other, you will have to remove most position:absolute declarations. position: absolute takes elements out of the document's flow, so it will not be aware of the elements around it (it's more complicated than that, but this is the short answer).

However, if you'd like to animate the opening and closing of the menu, you will have to define a height for the div in the open state. Unfortunately, it's not possible to animate to height: auto, which would be ideal in this case.

In the end, you will have to transition max-height or define a height (and then transition it), like in this demo: https://jsbin.com/hufihoh/edit?html,css,output

.menu {
  position: relative;
  top: 0px;
  display: flex;
  flex-direction: column;
  width: 235px;
  height: auto;
  margin: auto;
  padding: auto;
  border-bottom-color: rgba(0, 5, 10, 1.00);
  background-color: rgba(0, 5, 10, 1.00);
  background-repeat: repeat;
  background-clip: content-box;
}

.dropbtn {
  /* style the buttons*/
  position: relative;
  background-color: rgba(40, 40, 40, 1.00);
  color: darkorange;
  padding: 10px;
  margin-left: 0px;
  font-size: 16px;
  border: none;
  border-radius: 5px;
  font-family: monospace;
  width: 235px;
  transition: background 0.3s ease;
  cursor: pointer;
}

.dropdowns {
  /*initialize the revealing sliding menu*/
  margin: auto;
  display: block;
}

.dropdown-menu {
  overflow: hidden;
  max-height: 0;
  transition: max-height 1s ease;
}

.dropdown-menu .dropdown-content {
  display: block;
  background-color: black;
}

.dropdown-content a {
  display: block;
  color: white;
  padding: 12px 16px;
  text-decoration: none;
}

.dropdown-menu a:hover {
  background-color: darkorange;
  color: #000000;
}

.dropdown:hover .dropdown-menu {
  max-height: 400px;
}

.dropdown:hover .dropbtn {
  background-color: rgba(65, 65, 65, 1.00);
  color: white;
}
<div class="menu">
  <div class="dropdowns">
    <div class="dropdown dropdown1">
      <button class="dropbtn">DIV 1</button>
      <div class="dropdown-menu">
        <div class="dropdown-content">
          <a href="#">Link 1</a>
          <a href="#">Link 2</a>
          <a href="#">Link 3</a>
          <a href="#">Link 4</a>
          <a href="#">Link 5</a>
        </div>
      </div>
    </div>
    <div class="dropdown dropdown2">
      <button class="dropbtn">DIV 2</button>
      <div class="dropdown-menu">
        <div class="dropdown-content">
          <a href="#">Link 6</a>
          <a href="#">Link 7</a>
          <a href="#">Link 8</a>
          <a href="#">Link 9</a>
          <a href="#">Link 10</a>
        </div>
      </div>
    </div>
    <div class="dropdown dropdown3">
      <button class="dropbtn">DIV 3</button>
      <div class="dropdown-menu">
        <div class="dropdown-content">
          <a href="#">Link 11</a>
          <a href="#">Link 12</a>
          <a href="#">Link 13</a>
          <a href="#">Link 14</a>
          <a href="#">Link 15</a>
        </div>
      </div>
    </div>
  </div>
</div>

Another alternative, which I used in a project, albeit more complicated, is to store the number of elements in a custom property and then define the open div's height based on that property. I won't go into it too much, but it's a possibility.