Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootstrap 3 Navbar Dynamic Collapse

I am searching for a solution to a resizing issue with bootstrap's navbar.

Currently a navbar can have a sort of 'overlapping' effect before becoming compacted. (I am aware that this is due to media queries)

example from bootstraps site

Media queries are being used here to dictate when to go compact, however I am looking for a solution that will cause the navbar to resize ONLY when there is no room left between '.navbar-nav' and '.navbar-right'.

This is significant because '.navbar-nav' and '.navbar-right' have dynamic widths. (in other words sometimes '.navbar-nav' will contain anywhere from 1 list item to 5 list items. '.navbar-right' is similar in that it is a string of text that could be anywhere from 3 characters to potentially 100 characters long or even longer.

enter image description here

Below is a plunker example where by resizing the preview pane, you can see the unintended 'overlapping' taking place (as it waits for the max-width media query to be met).

http://plnkr.co/edit/7r5fNX2JyJUuT0PvVPDf?p=preview

How can I have it become compacted only when '.navbar-nav' and '.navbar-right' have no room between each other (say.. 5px of space between each other or something similar)?

(please note, adjusting the break points is not enough to accomplish this)

like image 319
captainrad Avatar asked Nov 27 '13 16:11

captainrad


4 Answers

You should add a custom class on your navbar, and change the style when it gain height :

<nav id="autocollapse" class="navbar navbar-default" role="navigation">
    ...
</nav>
function autocollapse() {
    var navbar = $('#autocollapse');
    navbar.removeClass('collapsed'); // set standart view
    if(navbar.innerHeight() > 50) // check if we've got 2 lines
        navbar.addClass('collapsed'); // force collapse mode
}

$(document).on('ready', autocollapse);
$(window).on('resize', autocollapse);
#autocollapse.collapsed .navbar-header {
    float: none;
}
#autocollapse.collapsed .navbar-toggle {
    display: block;
}
#autocollapse.collapsed .navbar-collapse {
    border-top: 1px solid transparent;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.1);
}
#autocollapse.collapsed .navbar-collapse.collapse {
    display: none!important;
}
#autocollapse.collapsed .navbar-nav {
    float: none!important;
    margin: 7.5px -15px;
}
#autocollapse.collapsed .navbar-nav>li {
    float: none;
}
#autocollapse.collapsed .navbar-nav>li>a {
    padding-top: 10px;
    padding-bottom: 10px;
}

Bootply
Forked Plunker

like image 55
zessx Avatar answered Nov 13 '22 05:11

zessx


May be worth a try with jQuery:

$(document).ready(function() {
    var width_full = $('.navbar-collapse').innerWidth();
    var width_left = $('.navbar-nav').outerWidth(true);
    var width_right = $('.navbar-right').outerWidth(true);
    if (width_full - (width_left + width_right) < 0)
    {
        // trigger collapse, you have to figure out what css changes
        // exactly are needed, for example:
        $('.navbar-toggle').css('display', 'inline');
    }
});
like image 23
Markus Kottländer Avatar answered Nov 13 '22 04:11

Markus Kottländer


There is no way for CSS to detect the line-wrapping by itself, so you'll need to redefine the styles for a particular width of media. You're line-wrapping appears to be happening around 910px;

Twitter Bootstrap (3) by default applies display:none to .collapse, and then reapplies display:block value using a media-query to a detect view-port width of greater than or equal to 768px width:

/* beginning at line 4412 in bootstrap.css,  v3.0.2 */  
@media (min-width: 768px) {

    ... /*other declarations ommitted here */

    .navbar-collapse.collapse {
        display: block !important;
        height: auto !important;
        padding-bottom: 0;
        overflow: visible !important;
    }

    ... /*other declarations ommitted here */
}

So you could override this with a couple of more specific media-queries for your navbar for the range of values where you need to hide it (between 768px and 910px):

@media (min-width: 768px)  and max-width (max-width: 910px){

    #bs-example-navbar-collapse-1{

        display:none !important;
    }
like image 1
Faust Avatar answered Nov 13 '22 05:11

Faust


For bootstrap 3.3.5 some styles are missing for zessx answer. use these ones instead:

    #autocollapse.collapsed .navbar-header {
        float: none;
    }
    #autocollapse.collapsed .navbar-left,.navbar-right {
        float: none !important;
    }
    #autocollapse.collapsed .navbar-toggle {
        display: block;
    }       
    #autocollapse.collapsed .navbar-fixed-top {
        top: 0;
        border-width: 0 0 1px;
    }       
    #autocollapse.collapsed .navbar-collapse.collapse {
        display: none!important;
    }
    #autocollapse.collapsed .navbar-nav {
        float: none!important;
        margin-top: 7.5px;
    }
    #autocollapse.collapsed .navbar-nav>li {
        float: none;
    }
    #autocollapse.collapsed .navbar-nav>li>a {
        padding-top: 10px;
        padding-bottom: 10px;
    }
    #autocollapse.collapsed .collapse.in{
        display:block !important;
    }

One more thing. zessx uses 50px for collapse. There's a round issue when you applies a Zoom to the explorer. The nav height could be 53px, for example, and then the menu will collapse. I suggest to change the 50px value to 70px. So here is my suggest:

function autocollapse() {
            var navbar = $('#autocollapse');
            navbar.removeClass('collapsed'); // set standart view
            if (navbar.innerHeight() > 70) // check if we've got 2 lines
                navbar.addClass('collapsed'); // force collapse mode
        }
like image 1
thejavo Avatar answered Nov 13 '22 05:11

thejavo