12

I would like to prevent the Bootstrap .dropdown-menu from ever being wider than the main nav bar (which I have restricted to be the width of the .container class). I'd like for the dropdown menu to take up the width of the container class, but it shouldn't extend beyond that on either side.

Any ideas how to accomplish this, preferably using CSS?

Here's an example of what it currently looks like and what I'd like it to look like: screenshot

Here's a boiler plate navbar with a dropdown menu that has one really long menu item:

<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>

<div class="container">
  <nav class="navbar navbar-default" role="navigation">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu" role="menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action a really long menu item that extends way beyond the limits of "container" and may even extend beyond the view port area to the right, making some of the text unreadable.</a></li>
            <li><a href="#">Something else here</a></li>
            <li class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </nav>
</div>
mike.bronner
  • 1,203
  • 1
  • 20
  • 39

1 Answers1

29

Explanation

Bootstrap's adds position: absolute to the .dropdown-menu class. As you may know, all absolutely positioned elements are positioned in relation to the first parent element they find with position: relative. In Bootstrap, this is provided by the .dropdown wrapper

So if you want to position the element relative to the container, and not the nav item, we'll have to remove relative positioning from the .dropdown wrapper. You can do this by resetting the value to the initial value for the position property, which is static.

Congratulations! The menu is no longer constrained by the .dropdown element, but we still have some work to do.

Because bootstrap was not intending to space constrain the menu, menu items are given the property white-space: nowrap so they'll extend as long as they need. Think lines of code inside code blocks here on stack overflow (1 line = 1 line). Since we want the line to eventually end, this won't do. So we'll reset the anchor tags back to white-space: normal.

At this point the .dropdown-menu should take up the full size of the .navbar (which itself takes up the full size of the .container). This is where yamm3 is doing something really cool. It sets left: auto on the dropdown-menu.

According to MDN on the left property:

auto is a keyword that represents:
for absolutely positioned elements, the position of the element based on the right property and treat width: auto as a width based on the content.

So setting the .dropdown-menu to left:auto will cause the menu to start in its current location and extend all the way to the right of the container.

Just Codes

Just add the .fill-width class to your .dropdown element and include the following CSS:

.fill-width.dropdown {
    position: static;
}
.fill-width.dropdown > .dropdown-menu {
    left: auto;
}
.fill-width.dropdown > .dropdown-menu > li > a {
   white-space: normal; 
}

Working Demo in jsFiddle

screenshot

.full-width.dropdown {
    position: static;
}
.full-width.dropdown > .dropdown-menu {
    right: 0;
}
.full-width.dropdown > .dropdown-menu > li > a {
   white-space: normal; 
}


.fill-width.dropdown {
    position: static;
}
.fill-width.dropdown > .dropdown-menu {
    left: auto;
}
.fill-width.dropdown > .dropdown-menu > li > a {
   white-space: normal; 
}
<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>


<div class="container">
    <div class="navbar navbar-inverse">

        <!-- Header -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" 
                    data-toggle="collapse" 
                    data-target=".navbar-collapse">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">
                Bootstrap 3 Skeleton
            </a>
        </div>
        <!-- Navbar Links -->
        <div class="collapse navbar-collapse">
            <ul class="nav navbar-nav">
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" 
                    data-toggle="dropdown">
                        Normal <span class="caret"></span>
                    </a>
                    <ul class="dropdown-menu" role="menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Long
                            </a></li>
                        <li class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>   
                <li class="dropdown full-width">
                    <a href="#" class="dropdown-toggle" 
                    data-toggle="dropdown">
                        Full Width <span class="caret"></span>
                    </a>
                    <ul class="dropdown-menu" role="menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Long
                            </a></li>
                        <li class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>          
                <li class="dropdown fill-width">
                    <a href="#" class="dropdown-toggle" 
                    data-toggle="dropdown">
                        Fill Width <span class="caret"></span>
                    </a>
                    <ul class="dropdown-menu" role="menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Really Long
                            </a></li>
                        <li class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>   
            </ul>
        </div>
    </div>
</div>
Community
  • 1
  • 1
KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • 4
    One thing to note: don't forget to add the above code to a media query, something like `@media (min-width: 768px)`, to make sure it doesn't tangle with the hamburger menu. Thanks for this really elegant solution @KyleMit – mike.bronner Oct 02 '14 at 16:20
  • 3
    You should write a book...or become a teacher. So easy to understand and the results you delivered were marvelous. – Uncle Iroh May 15 '16 at 07:13
  • 1
    This saves my day! Thank You @KyleMit – Felix Kamote May 19 '16 at 03:24
  • 2
    Awesome explanation and demonstration. @mike.bronner, I also needed the information for the media query. – Chris22 Dec 14 '16 at 04:27
  • 2
    @MaggewDotCom thanks for sharing this link from [this page on Stackoverflow](http://stackoverflow.com/questions/23547665/how-to-style-bootstrap-dropdown-menu-to-be-full-page-width) – Chris22 Dec 14 '16 at 04:32
  • How would you make full-width menu render correctly on tablet and mobile? In these views, the menus are falling below the menu container. Thanks – Chris22 Dec 21 '16 at 20:54
  • @Chris22, as with all things bootstrap, you'll need to make sure you [include some meta tags](http://getbootstrap.com/getting-started/#template), notably ``]. It appears to be working in all instances I've tested. Here's a [editable plunk](https://plnkr.co/edit/CAm2ar?p=preview) and a [runnable version](https://run.plnkr.co/plunks/CAm2ar/index.html). And here's the [results I get on different devices](http://imgur.com/a/Bz8VM). If you have a [mcve], you could open a new question. – KyleMit Dec 21 '16 at 21:56
  • @KyleMit thanks. I wish I could attach screenshots of what I'm seeing at smaller sizes of your original example above and in the [plunkr](https://plnkr.co/edit/CAm2ar?p=preview) and [runnable version](https://run.plnkr.co/plunks/CAm2ar/index.html) you include in your followup answer. This rendering isn't what I expected. It's why I asked the question -- the menus (for Fullwidth example) are falling **beneath and outside** of the dark background menu container instead of inside of it like "Normal" dropdown. Your [results](http://i.imgur.com/keNzw8l.png) show the expanded menu, not at small. – Chris22 Dec 22 '16 at 05:07
  • I've found what I want using Yamm3 -- ["Picture" link on main top navbar resized](http://geedmo.github.io/yamm3/). When I resize the browser for that link, the full-width dropdowns render _inside and directly beneath the menu item link_, not below all menu items and outside of the menu container. i didn't provide a [minimal, complete, and verifiable example](http://stackoverflow.com/help/mcve), because your menus verify at smaller screen sizes that they aren't rendering like the Yamm3 full-width menu does at those sizes, and maybe they aren't supposed to, but I wanted to know how to do that – Chris22 Dec 22 '16 at 05:32