skip to Main Content

The dropdown menu was (edit: is -> was) overflowing out of the screen (width-wise), after fixing it I’d like to know how to control the position of it better and how to make it so that it’s position isn’t relative to the div(.top-menu), but the dropdown button.

I’m pretty much a beginner with CSS and HTML as a whole, basically I don’t understand the position/display values but that’s not the point. Basically I’ve been reading W3School’s documentation I guess? I saw the Horizontal navbar page, and decided to change how I did it before (using 1 big div element for the whole menu and then little div elements inside).
Afterwards, I tried to make a dropdown menu basically just copying how they did it and noticed a problem, as said before the dropdown menu is going out of the width of the screen and some other problems aswell.

CSS:

.top-menu {
  height: 1lh;
  width: 100%;
  background-color: cadetblue;
  position: fixed;
  top: 0%;
  left: 0%;
  text-align: end;
  line-height: 6;
}

.top-menu a {
  padding-right: 25px;
  font-family: sans-serif;
}
ul.navbar {
  float: right;
  list-style-type: none;
  margin: 0;
  padding-right: 10px;
  width: auto;
}

li {
  display: inline;
  padding: 10px 12px;
  background-color: #dddddd;
}

.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #BBBBBB;
  min-width: 160px;
  max-width: 100vw;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  padding: 12px;
  z-index: 1;
  right: 0;
  top: 100%;
  box-sizing: border-box;
  transform: translateX(10%);
}

.dropdown:hover .dropdown-content {
  display: block;
  width: fit-content;
  text-align: center;
}

HTML

    <div id="top-menu" class="top-menu">
      <ul class="navbar">
        <li>a</li>
        <li>b</li>
        <li>c</li>
        <li>d</li>
        <li>e</li>
        <li>
          <div class="dropdown">
            <span>Mouse over me</span>
            <div class="dropdown-content">
              <p>Hello World!</p>
            </div>
          </div>
        </li>
      </ul>
    </div>

There’s also some JS code I copied from ChatGPT, but I don’t think it does anything so I didn’t include it.

The overflow problem is (kind of) fixed, basically the question is how would I control it’s position (except with translateX() because I want it to be aligned), width/height.
Also I would like to know; I noticed the top: 0%;, and saw that the menu is actually positioning itself relative to the whole top bar instead of the dropdown button. Is there any fix?

2

Answers


  1. Change display: inline-block; to display: inline;. This will cause div.dropdown to take up only as much space as it’s children. So the dropdown will appear at the bottom edge of "Mouse over me".

    <!DOCTYPE html>
    <html>
    
    <head>
        <style>
            .top-menu {
                height: 1lh;
                width: 100%;
                background-color: cadetblue;
                position: fixed;
                top: 0%;
                left: 0%;
                text-align: end;
                line-height: 6;
            }
    
            .top-menu a {
                padding-right: 25px;
                font-family: sans-serif;
            }
    
            .test {
                margin: auto;
                position: absolute;
                text-align: center;
                top: 40%;
                left: 40%;
                color: whitesmoke;
                background-color: blue;
                border: 1px solid black;
                width: 100px;
                padding: 20px 10px;
            }
    
            ul.navbar {
                float: right;
                list-style-type: none;
                margin: 0;
                padding-right: 10px;
                width: auto;
            }
    
            li {
                display: inline;
                padding: 10px 12px;
                background-color: #dddddd;
            }
    
            .dropdown {
                position: relative;
                display: inline;
            }
    
            .dropdown-content {
                display: none;
                position: absolute;
                background-color: #BBBBBB;
                min-width: 160px;
                max-width: 100vw;
                box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
                padding: 12px;
                z-index: 1;
                right: 0;
                top: 100%;
                box-sizing: border-box;
                transform: translateX(10%);
    
            }
    
            .dropdown:hover .dropdown-content {
                display: block;
                width: fit-content;
                text-align: center;
            }
        </style>
    </head>
    
    <body>
        <div id="top-menu" class="top-menu">
            <ul class="navbar">
                <li>a</li>
                <li>b</li>
                <li>c</li>
                <li>d</li>
                <li>e</li>
                <li>
                    <div class="dropdown">
                        <span>Mouse over me</span>
                        <div class="dropdown-content">
                            <p>Hello World!</p>
                        </div>
                    </div>
                </li>
            </ul>
        </div>
    </body>
    
    </html>
    Login or Signup to reply.
  2. Two things to update:

    • The padding being added to <li> elements is affecting the alignment/positioning of the .dropdown-content element. The .dropdown-content needs to consider this when being positioned.
    • The .dropdown display should be inline.

    Working Example:

    I only modified the .dropdown and .dropdown-content blocks:

    .top-menu {
      height: 1lh;
      width: 100%;
      background-color: cadetblue;
      position: fixed;
      top: 0%;
      left: 0%;
      text-align: end;
      line-height: 6;
    }
    
    .top-menu a {
      padding-right: 25px;
      font-family: sans-serif;
    }
    ul.navbar {
      float: right;
      list-style-type: none;
      margin: 0;
      padding-right: 10px;
      width: auto;
    }
    
    li {
      display: inline;
      padding: 10px 12px;
      background-color: #dddddd;
      box-sizing: border-box;
    }
    
    .dropdown {
      position: relative;
      display: inline;
    }
    
    .dropdown-content {
      display: none;
      position: absolute;
      background-color: #BBBBBB;
      min-width: 160px;
      max-width: 100vw;
      box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
      padding: 12px;
      z-index: 1;
      right: -12px;
      top: calc(100% + 10px);
      box-sizing: border-box;
    }
    
    .dropdown:hover .dropdown-content {
      display: block;
      width: fit-content;
      text-align: center;
    }
    <div id="top-menu" class="top-menu">
        <ul class="navbar">
            <li>a</li>
            <li>b</li>
            <li>c</li>
            <li>d</li>
            <li>e</li>
            <li>
                <div class="dropdown">
                    <span>Mouse over me</span>
                    <div class="dropdown-content">
                        <p>Hello World!</p>
                    </div>
                </div>
            </li>
        </ul>
    </div>

    A Better Approach:

    It is better if you do not add padding to the <li> elements, but instead to the children within the <li> elements. You will then have an easier time aligning the dropdown. See the example below.

    Note: I did update the css to use flex-box (more modern approach). You can just focus on how I changed where the padding is applied. It would still apply to your original code.

    .top-menu {
      
      /* css variable to keep padding consistent */
      --navbar-item-padding: 10px 12px;
      
      /* align children to the right */
      display: flex;
      justify-content: end;
      
      /* make nav 'sticky' to top */
      position: fixed;
      top: 0;
      left: 0;
      
      width: 100%;
      background-color: cadetblue;
    }
    
    .top-menu a {
      text-decoration: none;
      padding: var(--navbar-item-padding);
    }
    
    ul.navbar {
      /* display children in a row (horizontally) */
      display: flex;
      flex-direction: row;
      
      list-style-type: none;
      margin: 0;
    }
    
    li {
      /* vertically center content of li */
      display: flex;
      align-items: center;
      
      margin-right: 10px; /* use margin instead of padding so it does not modify the actual li's width */
      background-color: #dddddd;
    }
    
    .dropdown {
      position: relative; /* required for children to use absolute positioning */
    }
    
    .dropdown .dropdown-label {
      /* pad the label iteself so that we don't add padding to the parent, thus the .dropdown-content element can be positioned accurately */
      padding: var(--navbar-item-padding); 
    }
    
    .dropdown-content {
      display: none;
      position: absolute;
      background-color: #BBBBBB;
      min-width: 160px;
      max-width: 100vw;
      box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
      padding: 12px;
      z-index: 1;
      top: 100%; /* move down an amount equal to 100% of the parent element's height */ 
      right: 0;  /* align right edge with right edge of parent */
      /* left: 0; /* align left edge with left edge of parent */
      box-sizing: border-box;
    }
    
    .dropdown:hover .dropdown-content {
      display: block;
      text-align: center;
    }
     <div id="top-menu" class="top-menu">
          <ul class="navbar">
            <li><a href="#">a</a></li>
            <li><a href="#">b</a></li>
            <li><a href="#">c</a></li>
            <li><a href="#">d</a></li>
            <li><a href="#">e</a></li>
            <li>
              <div class="dropdown">
                <div class="dropdown-label">Mouse over me</div>
                <div class="dropdown-content">
                  <p>Hello World!</p>
                </div>
              </div>
            </li>
          </ul>
        </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search