3

Explanation

I have this Bootstrap's navigation bar that has a horizontal responsive menu, but it is showing a horizontal scrollbar. I've listed below some attempts to hide/remove (and still scroll) this scrollbar, but nothing works properly.

Attempt 1: Use overflow-x: hidden, but then it won't scroll horizontally.
Attempt 2: Use ::-webkit-scrollbar {display: none;}, but it only works on webkit's based browsers.
Attempt 3: As suggested in this answer, I tried to use this code below, but then the submenu's (when navigation is expanded) size was changed and the scrollbar was still in there. You can see it in this fiddle.

#parent{
    height: 100%;
    width: 100%;
    overflow: hidden;
}

#child{
    width: 100%;
    height: 100%;
    overflow-y: scroll;
    padding-right: 17px; /* Increase/decrease this value for cross-browser compatibility */
}

/*I changed overflow-y to overflow-x and padding-right to padding-bottom*/

Is there any way that works on most browsers?

Sample code

You can also see on JSFiddle.

#navigation {
    background-color: rgba(230, 104, 92, 1);
}

.navbar-toggle i, .navbar-brand, .navbar-nav li a {
    color: #fff;
}

.nav {
    white-space: nowrap;
    display: -webkit-flex;
    display: -moz-flex;
    display: -ms-flex;
    display: -o-flex;
    display: flex;
}
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
</head>

<body id="body">

    <header id="navigation" class="navbar navbar-fixed-top">
        <div class="container">

            <div class="navbar-header">

                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <i class="fa fa-bars fa-2x" aria-hidden="true"></i>
                </button>

                <a class="navbar-brand" href="#body">
                    Logo
                </a>

            </div>

            <nav class="collapse navbar-collapse navbar-right" role="navigation">
                <ul id="nav-js" class="nav navbar-nav">
                    <li><a href="#">Item1</a></li>
                    <li><a href="#">Item2</a></li>
                    <li><a href="#">Item3</a></li>
                    <li><a href="#">Item4</a></li>
                    <li><a href="#">Item5</a></li>
                    <li><a href="#">Item6</a></li>
                    <li><a href="#">Item7</a></li>
                    <li><a href="#">Item8</a></li>
                    <li><a href="#">Item9</a></li>
                    <li><a href="#">Item10</a></li>
                    <li><a href="#">Item11</a></li>
                    <li><a href="#">Item12</a></li>
                    <li><a href="#">Item13</a></li>
                    <li><a href="#">Item14</a></li>
                    <li><a href="#">Item15</a></li>
                </ul>
            </nav>

        </div>
    </header>

    <script src="https://code.jquery.com/jquery-3.1.1.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    
</body>

</html>

Thanks in advance,
Luiz.

Community
  • 1
  • 1
Luiz
  • 1,275
  • 4
  • 19
  • 35

2 Answers2

2

The best way you can solve this problem it to change your menu structure. You're always going to have some sort of overflow problem because of the nature of the dom tree and the number of menu items you have. The best way to approach this would be to think what content your menu items are going to have then nest them. An example being:

<ul>
<li>Main A</li>
<li>Main B
  <ul>
    <li>Sub 1 of Main B</li>
    <li>Sub 2 of Main B</li>
  </ul>
</li>
</ul>

Having the overflow property hiding items that are intrinsic to the site's usability and navigation is going to be a huge headache in the long-term. Also you'll always have the scroll bar because you're breaking the width value of the containing element, and making it wider that the highest level parent element, which means there is no other way to view the items.

pjk_ok
  • 618
  • 7
  • 35
  • 90
  • I agree. Browsers put a scroll bar there for UX and accessibility purposes. By default, your users will not be confused if they see a scroll bar. – Ralph David Abernathy Mar 05 '17 at 16:06
  • sorry, I didn't understand. You mean that hide the scrollbar isn't possible? I'm trying to achieve something like [medium.com](https://medium.com)'s responsive navigation bar. – Luiz Mar 05 '17 at 16:33
  • Sorry, I looked at Medium's desktop site. I've seen what you mean now on the mobile version. Using overflow:hidden won't create this menu. As you can see from Neophyte's answer, this will just cut off the menu items. You'll be able to do this with Javascript. Let me put my thinking cap on and see what I can come up with. – pjk_ok Mar 05 '17 at 16:51
  • Have you tried adding padding to left and right like they have on the Medium site? – pjk_ok Mar 05 '17 at 16:58
  • Sorry for taking this long, I was answering Neophyte. You mean to add padding to left and right as Neophyte did below? Sorry, I didn't understand where to add this. – Luiz Mar 05 '17 at 17:29
2

You can achieve it in the following way-- used media queries to have the effect only in small screen view.

As we are giving position:relative to the parent and position:absolute to child we need to hard code the height of the parent. that's why the height changed.

#parent {
  width: 100%;
  height: 70px;
}

Also give some padding left to mid align it, like this--

padding right is necessary to be ale to scroll.

#child {

  padding-right: 150px;
  padding-left: 25px;
}

working example

#navigation {
    background-color: rgba(230, 104, 92, 1);
}

.navbar-toggle i, .navbar-brand, .navbar-nav li a {
    color: #fff;
}

.nav {
    white-space: nowrap;
    display: -webkit-flex;
    display: -moz-flex;
    display: -ms-flex;
    display: -o-flex;
    display: flex;
}
@media screen and (max-width: 768px) {
#child,
#parent {
  width: 120%;
  height: 70px;
}
#parent {
  
  position: relative;
  overflow: hidden;
}
#child {
  position: absolute;
  left: 0;
  overflow-y: hidden;
  overflow-x: scroll;
  padding-right: 150px;
  padding-left: 25px;
}
#child::-webkit-scrollbar {
  display: none;
}
.navbar-nav > li {
      margin-left: 10px;
}
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
</head>

<body id="body">

    <header id="navigation" class="navbar navbar-fixed-top">
        <div class="container">

            <div class="navbar-header">

                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <i class="fa fa-bars fa-2x" aria-hidden="true"></i>
                </button>

                <a class="navbar-brand" href="#body">
                    Logo
                </a>

            </div>

            <nav id="parent" class="collapse navbar-collapse navbar-right" role="navigation">
                <ul id="child" class="nav navbar-nav">
                    <li><a href="#">Item1</a></li>
                    <li><a href="#">Item2</a></li>
                    <li><a href="#">Item3</a></li>
                    <li><a href="#">Item4</a></li>
                    <li><a href="#">Item5</a></li>
                    <li><a href="#">Item6</a></li>
                    <li><a href="#">Item7</a></li>
                    <li><a href="#">Item8</a></li>
                    <li><a href="#">Item9</a></li>
                    <li><a href="#">Item10</a></li>
                    <li><a href="#">Item11</a></li>
                    <li><a href="#">Item12</a></li>
                    <li><a href="#">Item13</a></li>
                    <li><a href="#">Item14</a></li>
                    <li><a href="#">Item15</a></li>
                </ul>
            </nav>

        </div>
    </header>

    <script src="https://code.jquery.com/jquery-3.1.1.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    
</body>

</html>

If it looks like breaking use in firefox write browser specific css..increase the margin between nav-items.

<style type="text/css">
 @-moz-document url-prefix() {
 .navbar-nav > li {
  margin-left: 10px;/*set this to such a value so that it doesn't look like 
   it is breaking*/
  }
   }
    </style>

Hope this helps!

neophyte
  • 6,540
  • 2
  • 28
  • 43
  • Thank you for the attention, but the items inside the submenu aren't centered positioned anymore and the submenu's size is changed for some reason =( – Luiz Mar 05 '17 at 16:36
  • the height has changed because i hard coded it..change it according to your need. and give some padding-left it will be centered.. – neophyte Mar 05 '17 at 16:39
  • Sorry for taking so long, I was testing it in others browsers. It worked great on every browser, but on Firefox it shows a part of the scrollbar. And for some reason, it looks like to "break" (as it was going to wrap) the items, as you can see in [this print](http://i.imgur.com/2riSUZS.png) - it happens on every browser. By the way, thank you again!! – Luiz Mar 05 '17 at 17:22
  • It is not actually breaking ..it is happening because every browser sets their own width.. write browser specific css..increase the margin between the elements..wait showing you how to do it – neophyte Mar 05 '17 at 17:32
  • Sorry, I think you misunderstood. This breaking problem happens with every browser. As you can see [here](http://i.imgur.com/2riSUZS.png), the item looks like to be inside a container, so it "breaks" before the end of the browser's width (when it should not "break" at all - following the `white-space: nowrap;`'s effect). – Luiz Mar 05 '17 at 17:46
  • sorry give `width=120%;` it will do check updated snippet. also manipulate the margin-left to overcome the breaking problem..this is the only way i know to achieve what you want – neophyte Mar 05 '17 at 17:51
  • I set to 120%, but then the last item (15) were missing, then I set to 110% (which is the minimum, since 109% still breaks), but the last item is still compromised =( – Luiz Mar 05 '17 at 17:59