javascript – how to make twitter bootstrap submenu to open on the left side?-ThrowExceptions

Exception or error:

I was trying to create twitter bootstrap submenu in dropdown menu, but I’ve got a problem: I have dropdown menu in the top right corner of the page and that menu has one more submenu. However, when submenu opens – it does not fit in the window and goes too much to the right, so that user can see only first letters. How to make that submenu to open not to the right, but to the left?

How to solve:

The simplest way would be to add the pull-left class to your dropdown-submenu

<li class="dropdown-submenu pull-left">

jsfiddle: DEMO

###

If I’ve understood this right, bootstrap provides a CSS class for just this case. Add ‘pull-right’ to the menu ‘ul’:

<ul class="dropdown-menu pull-right">

..and the end result is that the menu options appear right-aligned, in line with the button they drop down from.

###

Curent class .dropdown-submenu > .dropdown-menu have left: 100%;. So, if you want to open submenu on the left side, override those settings to negative left position. For example left: -95%;. Now you will get submenu on the left side, and you can tweak other settings to get perfect preview.

Here is DEMO

EDIT: OP’s question and my answer are from august 2012. Meanwhile, Bootstrap changed, so now you have .pull-left class. Back then, my answer was correct. Now you don’t have to manually set css, you have that .pull-left class.

EDIT 2: Demos aren’t working, because Bootstrap changed their URL’s. Just change external resources in jsfiddle and replace them with new ones.

###

If you are using bootstrap v4 there is a new way to do that.

You should use .dropdown-menu-right on the .dropdown-menu element.

<div class="btn-group">
  <button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Right-aligned menu
  </button>
  <div class="dropdown-menu dropdown-menu-right">
    <button class="dropdown-item" type="button">Action</button>
    <button class="dropdown-item" type="button">Another action</button>
    <button class="dropdown-item" type="button">Something else here</button>
  </div>
</div>

Link to code: https://getbootstrap.com/docs/4.0/components/dropdowns/#menu-items

###

The correct way to do the task is:

/* Submenu placement itself */
.dropdown-submenu > .dropdown-menu { left: auto; right: 100%; }
/* Arrow position */
.dropdown-submenu { position: relative; }
.dropdown-submenu > a:after { position: absolute; left: 7px; top: 3px; float: none; border-right-color: #cccccc; border-width: 5px 5px 5px 0; }
.dropdown-submenu:hover > a:after { border-right-color: #ffffff; }

###

I have created a javascript function that looks if he has enough space on the right side.
If it has he will show it on the right side, else he will display it on the left side

Tested in:

  • Firefox (mac)
  • Chorme (mac)
  • Safari (mac)

Javascript:

$(document).ready(function(){
    //little fix for the poisition.
    var newPos     = $(".fixed-menuprofile .dropdown-submenu").offset().left - $(this).width();
    $(".fixed-menuprofile .dropdown-submenu").find('ul').offset({ "left": newPos });

    $(".fixed-menu .dropdown-submenu").mouseover(function() {
        var submenuPos = $(this).offset().left + 325;
        var windowPos  = $(window).width();
        var oldPos     = $(this).offset().left + $(this).width();
        var newPos     = $(this).offset().left - $(this).width();

        if( submenuPos > windowPos ){
            $(this).find('ul').offset({ "left": newPos });
        } else {
            $(this).find('ul').offset({ "left": oldPos });
        }
    });
});

because I don’t want to add this fix on every menu items I created a new class on it.
place the fixed-menu on the ul:

<ul class="dropdown-menu fixed-menu">

I hope this works out for you.

ps. little bug in safari and chrome, first hover will place it to mutch to the left will update this post if I fixed it.

###

If you have only one level and you use bootstrap 3 add pull-right to the ul element

<ul class="dropdown-menu pull-right" role="menu">

###

Actually – if you are ok with floating the dropdown wrapper – I’ve found it to be as easy as to add navbar-right to the dropdown.

This seems like cheating, since it’s not in a navbar, but it works fine for me.

<div class="dropdown navbar-right">
...
</div>

You can then further customize the floating with a pull-left directly in the dropdown

<div class="dropdown pull-left navbar-right">
...
</div>

… or as a wrapper around it …

<div class="pull-left">
  <div class="dropdown navbar-right">
  ...
  </div>
</div>

###

If you’re using LESS CSS, I wrote a little mixin to move the dropdown with the connecting arrow:

.dropdown-menu-shift( @num-pixels, @arrow-position: 10px ) {  // mixin to shift the dropdown menu
    left: @num-pixels;
    &:before { left: -@num-pixels + @arrow-position; }        // triangle outline
    &:after  { left: -@num-pixels + @arrow-position + 1px; }  // triangle internal
}

Then to move a .dropdown-menu with an id of dropdown-menu-x for example, you can do:

#dropdown-menu-x {
    .dropdown-menu-shift( -100px );
}

###

I have created a javascript function that looks if he has enough space on the right side. If it has he will show it on the right side, else he will display it on the left side. Again if it has has enough space on the right side, it will show right side. it is a loop…

$(document).ready(function () {

$('body, html').css('overflow', 'hidden');
var screenWidth = $(window).width();
$('body, html').css('overflow', 'visible');

if (screenWidth > 767) {

    $(".dropdown-submenu").hover(function () {

        var dropdownPosition = $(this).offset().left + $(this).width() + $(this).find('ul').width();
        var newPosition = $(this).offset().left - $(this).find('ul').width();
        var windowPosition = $(window).width();

        var oldPosition = $(this).offset().left + $(this).width();
        //document.title = dropdownPosition;
        if (dropdownPosition > windowPosition) {
            $(this).find('ul').offset({ "left": newPosition });
        } else {
            $(this).find('ul').offset({ "left": oldPosition });
        }
    });

}

});

###

Are you using the latest version of bootstrap? I have adapted the html from the Fluid Layout example as shown below. I added a drop down and placed it furthest to the right hand side by adding the pull-right class. When hovering over the drop down menu it is automatically pulled to the left and nothing is hidden – all the menu text is visible. I have not used any custom css.

<div class="navbar navbar-inverse navbar-fixed-top">
  <div class="navbar-inner">
    <div class="container-fluid">
      <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </a>
      <a class="brand" href="#">Project name</a>
      <div class="nav-collapse collapse">
        <ul class="nav pull-right">
          <li class="active"><a href="#">Home</a></li>
          <li><a href="#about">About</a></li>
          <li><a href="#contact">Contact</a></li>
          <li class="dropdown open">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
            <ul class="dropdown-menu">
              <li><a href="#">Action</a></li>
              <li><a href="#">Another action</a></li>
              <li><a href="#">Something else here</a></li>
              <li class="divider"></li>
              <li class="nav-header">Nav header</li>
              <li><a href="#">Separated link</a></li>
              <li><a href="#">One more separated link</a></li>
            </ul>
          </li>
        </ul>
        <p class="navbar-text pull-right">
          Logged in as <a href="#" class="navbar-link">Username</a>
        </p>
      </div><!--/.nav-collapse -->
    </div>
  </div>
</div>

Leave a Reply

Your email address will not be published. Required fields are marked *