29

I want to use a fixed header in my Bootstrap modal, however if I set .modal-header as position:fixed it scrolls along with the moda content. How do I create a trully fixed header in BS modal?

johnkavanagh
  • 4,614
  • 2
  • 25
  • 37
Lucas Zardo
  • 355
  • 1
  • 3
  • 7
  • 1
    You kind of want to go back to the old modals from Bootstrap 2. In the new one, the whole `.modal` scrolls, so setting the `.modal-header` to fixed won't work. You'll need to stop the modal scrolling, set a height on the `.modal-content` and have that scroll instead. – davidpauljunior Feb 05 '14 at 22:53

6 Answers6

99

Instead of trying to make the header fixed, just fix the height of the body and make it scrollable. That way the header (and footer) will always be visible.

You can easily do this using the CSS3 vh unit together with calc. Both vh as calc have pretty good browser support (IE9+).

The vh unit is relative to the viewport (= browser window) height. 1 vh is 1% of the height and 100vh means 100% of the viewport height.

We just need to substract the height of the modal's header, footer and margins. It's going to be difficult it that dynamic. If those sizes are fixed, we just add all the heights.

Set either the height or max-height to calc(100vh - header+footer px).

.modal-body {
    max-height: calc(100vh - 210px);
    overflow-y: auto;
}

See the jsfiddle

Arnold Daniels
  • 16,516
  • 4
  • 53
  • 82
  • 3
    Thank you! this should be set as the answer! Only having issues adjusting the height of the modal now but will probably fix that soon :) – Gcap Dec 07 '15 at 20:19
  • If you happen to be using LESS and having problems with this, see https://stackoverflow.com/questions/11972084/less-aggressive-compilation-with-css3-calc. – bbodenmiller Nov 19 '16 at 10:27
8

Here's a simple trick. Let me assume that i have to fix the div with class "fixedHeader"

Simple Jquery Way:

$('.modal').scroll(function() {
     var a=$('.modal').scrollTop();
     $('.fixedHeader').css('top',a+'px');
});

CSS

.fixedHeader {
    position:fixed;
}

Whatever i have answered above is for normal bootstrap using jquery.But if someone is using angular bootstrap for the modal then

Angular

$timeout(function() {
    angular.element('.modal').scroll(function() {
        var a = angular.element('.modal').scrollTop();
        angular.element('.fixedHeader').css('top', a + 'px');
    });
}, 10);
/*Put the above in modalinstance controller*/
/*timeout is necessary as you want to run the function after the modal is loaded or sometimes it may be unable to find the class '.modal' */

CSS

.fixedHeader {
    position:fixed;
}

Make sure you have jquery dependency installed in both cases.

bbird
  • 368
  • 1
  • 6
ritz078
  • 2,193
  • 3
  • 22
  • 24
4

My solution may seem a little silly, but it details the steps I took to solve this problem for my use case.

I tried something like ritz078's answer, but what I found was that it did not work well on iOS when scrolling, since Safari likes to do things its own way.

So, my solution was to duplicate the bit of code I wanted to affix and place that duplicate code outside of the modal altogether in its own hidden wrapper:

<div class="fixed-header">
    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
        <h4 class="modal-title">Modal title</h4>
    </div>
</div>

Then I used JS to 1) make the duplicate code visible after I scroll through the modal a bit, 2) close the duplicate code whenever I click out of the modal, and 3) restore functionality to the duplicate modal's close button:

$('#myModal').on('scroll', function() {
    var threshold = 60;

    if ($('#myModal').scrollTop() > threshold) {
        $('.fixed-header').addClass('affixed');
    }
    else {
        $('.fixed-header').removeClass('affixed');
    }
});

$('#myModal').on('hide.bs.modal', function (e) {
    $('.fixed-header').removeClass('affixed');
});

$('.fixed-header button').click(function() {
    $('#myModal').modal('hide');
});

The challenge here is matching the modal's styling (particularly its width and margins), but this solution lets you scroll the modal freely on iOS without looking funky, which was my goal.

JSFiddle (forked from Jasny's answer to show how it's different in scope from his answer)

Community
  • 1
  • 1
Brendan
  • 868
  • 1
  • 16
  • 38
3

As per my comment, this was actually an improvement in Bootstrap 3. Allowing long content and having the whole modal scroll, not just the 'content' of the modal.

You can override it with something like this, but it's not as nice functionality.

.modal {
  overflow: hidden;
}

.modal-body {
  height: 300px;
  overflow: auto;
}

Demo

davidpauljunior
  • 8,238
  • 6
  • 30
  • 54
  • Thanks, but actually I want to use this BS improvement alongside a fixed header. I'm using modals as a quick product viewer and when user select options, prices change. I want to use header to inform user of changes in final price, so they don't get surprised when ends scrolling. – Lucas Zardo Feb 05 '14 at 23:51
  • You can't have a whole modal scrolling and have a fixed header on that modal. The header would have to be outside the modal. – davidpauljunior Feb 06 '14 at 00:02
1

In javascript add a class to modal:

windowClass: 'framework-modal'

In css adjust o modal-body:

.framework-modal .modal-body {
    max-height: 600px;
    overflow: auto;
}
Edmilson Lani
  • 153
  • 2
  • 6
-2

In Body content

CSS:

body{
    overflow:hidden;
}
Suresh Karia
  • 17,550
  • 18
  • 67
  • 85
ramiz
  • 1
  • 1