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?
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
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.
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">Ă—</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)
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
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;
}
In Body content
CSS:
body{
overflow:hidden;
}
Related
So, I'd like to set the height of the collapsed navigation of bootstrap to 100% height.
e.g. https://getbootstrap.com/examples/navbar/ this should span over the whole screen.
I did some research and mostly found people using height: 100vh; but this is not dynamics, shouldn't matter too much in the end though, but I still don't like it.
Usually, one could e.g. do:
<div id="bar">
<div id="foo">
test
</div>
</div>
html,
body {
height: 100%;
}
#foo, #bar{
background-color: red;
min-height: 100%;
}
But I'm asking myself now, what's the best approach to implement this when using bootstrap v3.
you can hide the Content while the Navigation is collapsed using JavaScript..
for example: document.getElementById("ID").style.display = none;
if there is no content under the Navigation, there is nothing to scroll... :P
So I'm asking myself then, how I can deactive scrolling when the navigation collapsed?
I somehow fail listening to the proper event
As per your comment, I see the issue is that you dont get the proper point of the collapse. The plugin provides the events on collapse.
By bootstrap documentation this is how you do
$('#foo').on('hidden.bs.collapse', function () {
// do something…
})
I am almost done with a simple 2-page website for my registered domain names.
Unfortunately I have one small issue I can't seem to fix: a jumpy header when a Twitter Bootstrap modal opens and closes.
On mobile devices there's no problem. The problem only occurs in larger viewports like desktops and laptops.
How to recreate
Open http://www.domains.cloudlabz.nl/domains in a webbrowser and make sure you get a vertical scrollbar by lowering the viewport height.
Click on one of the blue 'more info' buttons.
Notice the jumping header and disappearing scrollbar once the modal opens.
Close the modal and notice the header jumping back and the scrollbar reappearing.
Check the following image (same result in Opera, Safari, Firefox and Chrome):
What I'd like
I'd like the header to stop jumping when opening/closing a modal. The fact the scrollbar disappears is not an issue. Actually, I would like it to stay like that.
Update
I noticed the jumping header only occurs with fixed position elements such as my header (added Bootstrap class navbar-fixed-top). It even occurs on the Bootstrap website itself: http://getbootstrap.com/javascripts. Go to the 'Modals > Optional Sizes' area on a desktop and click one of the buttons. You'll see the right side menu jumping back and forth.
When the modal opens, the class .modal-open is added to the body element (thanks for pointing that out #Pred). It adds a padding of 15px to the right, which is the same width as the scrollbar gutter. This prevents the body from jumping back and forth.
Unfortunately this padding apparently does not apply to fixed elements.
Bootstrap adds class="modal-open" and padding-right: 15px; to body when the modal is shown. To remove the right shift and keep the scroll bar add this to your css:
body.modal-open {
overflow: inherit;
padding-right: 0 !important;
}
Tried in bootstrap 3.3.4
I seemed to have found a quick fix for my issue. It uses a piece of javascript to add extra style to the header (15px padding-right) to prevent it from jumping.
This might not be the best solution but for now it works just fine.
Since there were no issues on viewports smaller than 768px (mobile) this piece of code only adds the extra 15px to larger viewports such as desktops and laptops
<script>
$(document).ready(function(){
// Dirty fix for jumping scrollbar when modal opens
$('#requestModal').on('show.bs.modal', function (e) {
if ($(window).width() > 768) {
$(".navbar-default").css("padding-right","15px");
}
});
$('#requestModal').on('hide.bs.modal', function (e) {
if ($(window).width() > 768) {
$(".navbar-default").css("padding-right","0px");
}
});
});
</script>
If you know a better solution (preferably CSS3 only), please let me know.
Thanks for all the help!
As you usually put Bootstrap navbar as a direct child of the body container:
<body>
<nav class="navbar navbar-fixed-top">...</nav>
</body>
You can use the body padding-right value, calculated in the Bootstrap core code to prevent it from "jumping" when opening a modal window, to fix the navbar issue as well . A pure CSS solution is below:
.navbar-fixed-top {
padding-right: inherit;
}
Easy as that.
When the modal opens, the "modal-open" class is added to the HTML <body> element which hides overflow. You can change this by over-writing the "modal-open" class with overflow: inherit. This will keep the scrollbar in view, just as it is when the modal is closed. Keep in mind that this will change the overflow option whenever any modal is opened on the page. Hope this helps. Good luck!
All this happens because of this part of code in bootstrap.js:
Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
}
That annoying problem happens in Firefox 32.0 (Gecko/20100101) and Chromium Version 37.0.2062.94 (Webkit 537.36) (Ubuntu 14.04). Not happens in QupZilla Version 1.6.6 (WebKit 537.21).
For me, the dirty fix is to comment the conditional line, after that it works in all browsers I tested (including some android's browsers).
NOTE: if you comment that line, you should be careful with the size of your modals since bootstrap will not create enough space for the new scrollbar.
Regards.
Another solution is to add:
.modal-open .navbar-fixed-top {
overflow-y: scroll;
}
to prevent its content from jumping. Again, easy as that.
This one only works if you know your page content is longer than the viewport (so any long scrolling page). You can just add the following to your CSS -
html {
overflow-y: scroll;
}
.modal-open {
padding-right: 0!important;
}
I came around same issue and I solved it as follows
just add
body.modal-open {
position: fixed;
overflow: scroll;
width: 100%;
padding-right: 0!important;
}
I manually change bootstap.js:
before change
Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
}
Modal.prototype.resetScrollbar = function () {
this.$body.css('padding-right', '')
}
after change:
Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
var headerPad = parseInt(($('.navbar-fixed-top').css('padding-right') || 0), 10)
if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
if (this.bodyIsOverflowing) $('.navbar-fixed-top').css('padding-right', headerPad + this.scrollbarWidth)
}
Modal.prototype.resetScrollbar = function () {
this.$body.css('padding-right', '')
$('.navbar-fixed-top').css('padding-right', '')
}
I have a structure:
<html>
<body>
<nav class="navbar navbar-fixed-top">...</nav>
<section>
<div class="container">...</div>
</section>
<section>
<div class="container">...</div>
</section>
<footer>...</foter>
</body>
</html>
I'm using this CSS:
body.modal-open {padding-right: 0 !important}
body.modal-open nav,
body.modal-open section,
body.modal-open footer {padding-right: 17px !important}
Add the following to your CSS:
body {
overflow: inherit;
padding-right: 0 !important;
}
For Bootstrap 4 sticky-top, use the following snippet. Tested all the CSS solutions on this page but none worked for Bootstrap 4.
<script type="text/javascript">
$('body').on('show.bs.modal', function () {
$('.sticky-top').css('margin-left', '-=0px');
});
$('body').on('hidden.bs.modal', function () {
$('.sticky-top').css('margin-left', 'auto');
});
</script>
My page design was as follows
<header class="container">
<div class="row">
</div>
</header>
<div class="container sticky-top">
<nav class="navbar navbar-expand-lg">
This div jumped/shifted 17px to the right when opening a modal
</nav>
</div>
In my case, it can be solved by adding comments or remove these two lines right: 0; and left: 0; in bootstrap.css file:
.navbar-fixed-top,
.navbar-fixed-bottom {
position: fixed;
/* right: 0;
left: 0; */
z-index: 1030;
}
Note: I use bootstrap v3.3.7
In 4.5, the following code solved my issue of the fixed header sliding left.
body.modal-open {
position: fixed;
overflow-y: scroll;
width: 100%;
padding-right: 0!important;
}
.modal-open .fixed-top {
padding-right: inherit!important;
}
I have a body with a wrapper
<body>
<div class="wrapper">//loads of content</div>
</body>
The wrapper is set to position: fixed; Because of special scroll-behaviour and javascript. I would like the body to have the same height as the wrapper.
(If anyone is intersted in why I try to achive this I try to explain my problem here:
Setting height of fixed element
But I felt the question got overly complicated for anyone who wants to solve this issue.)
First thing, you can set .wrapper's height that is of body through CSS like this:
height: inherit;
Here inherit will take out its parent's height and then set it as its.
Second thing, you need javascript for that because if you will use CSS then I am afraid you will not be able to control the size of the body when resizing.
With CSS:
height: whatever_body_height
With JS:
function getDocHeight() { /*For cross-browser*/
var D = document;
return Math.max(
D.body.scrollHeight, D.documentElement.scrollHeight,
D.body.offsetHeight, D.documentElement.offsetHeight,
D.body.clientHeight, D.documentElement.clientHeight
);
}
window.onresize = function () {
document.getElementByClassName('.wrapper').style.height = getDocHeight();
}
Hope it helped.
This is probably not possible with CSS, but maybe I'm wrong:
I have a document structure like this:
BODY
DIV[A]
DIV[B]
DIV[A] is position:absolute with fixed with and centered on screen. It has no height setting.
DIV[B] is position:absolute with top:300px. This is the actual content DIV. Inside that, I position everything with position:absolute. Because I love position:absolute. It gives full control over positioning. No ugly text flow headaches... it's so nice.
Ok. But the problem now: DIV[B] is always only that height what I tell it to be. Now, maybe there's a cool CSS trick that would pull it always down to touch the bottom of the browser viewport?
To set the height to dynamically be the window height - DIV[A]'s height, you'll have to use JavaScript/jQuery and keep calling it with a SetTimeout.
Alternately, if it suits your needs, you can set DIV[B] to be position:fixed; bottom:0px;
<body onload="setupLayout();" >
...
<script language="javascript" type="text/javascript">
// ACTIVITIES TO RUN FOR THE PAGE
function setupLayout() {
setInterval('adjustLayout();', 1000);
}
// ADUST THE MAIN CONTAINER (content panel) LAYOUT
function adjustLayout() {
try {
var divB = $get('divB');
var divAHeight = 20px;
divB.style.height = document.body.clientHeight - divAHeight ;
}
catch (e) { }
}
</script>
</body>
#div_to_touch_the_bottom {
position:fixed;
bottom:0;
top:0;
left:25%;
right:25%;
}
This DIV will touch the bottom of viewport, you can modify its left and right according to your needs. I am not sure that this the answer you are lookign for but it could be a good start
When you want DIV to be a position:absolute, it should be in a position: relative container.
<div style="position: relative">
<div style="position: absolute; top: 300px">
<h3>Content Header</h3>
<!-- Content -->
</div>
</div>
So regarding your problem with DIV[B], you can mix between <table>s and <div>s.
I suppose DIV[A] is your header and DIV[B] your main content div and you would like to always have your content div take all the page when there is not a lot of text in it, right?
If I remember correctly, because I can't test it at the moment, you could:
html, body {
height: 100%;
}
DIV[B] {
height: 100%;
}
I think that should do the trick.
Edit: Here is a good example that might help you: http://www.xs4all.nl/~peterned/examples/csslayout1.html
i wonder if this is possible with simple css or if i have to use javascript for this?
i have a sidebar on my website. a simple div#sidbar it's normally about 1024px high, but the height changes dynamically due to it's content.
so let's imaginge the following case:
<div id="sidebar">
<div class="widget"></div> //has a height of 100px
<div class="widget"></div> //has a height of 100px
<div id="rest"></div> //this div should have the rest height till to the bottom of the sidebar
</div>
i want the div#rest to fill out the rest of the sidebar till it reaches the bottom of the div#sidebar.
is this possible with pure css?
If you know the exact height of #widget (100px in your case), you can avoid using JavaScript by using absolute positioning:
#sidebar
{
height: 100%;
width: ...;
position: relative;
}
.widget
{
height: 100px;
}
#rest
{
position: absolute;
left: 0;
width: 100%;
top: 200px;
bottom: 0;
}
What you want is something like 100% - 200px but CSS doesn't support expressions such as these. IE has a non-standard "expressions" feature, but if you want your page to work on all browsers, I can't see a way to do this without JavaScript. Alternatively, you could make all the divs use percentage heights, so you could have something like 10%-10%-80%.
Update: Here's a simple solution using JavaScript. Whenever the content in your sidebar changes, just call this function:
function resize() {
// 200 is the total height of the other 2 divs
var height = document.getElementById('sidebar').offsetHeight - 200;
document.getElementById('rest').style.height = height + 'px';
};
I propose the table-element as an alternative:
+: clean CSS
+: avoiding javascript
-: table semantically misused
-: not the requested div-elements
I came across this question while looking for an answer to a similar question, and I thought I'd illustrate calc. As of this post, calc is not yet supported cross-browser; however, you can check this link here to see if your target browsers are supported. I've modified matt's hypothetical case to use calc in an example on jsFiddle. Essentially it is a pure CSS solution that does what casablanca proposes in his answer. For example, if a browser supports calc, then height: calc(100% - 200px); would be valid as well as for similar properties.
Sometimes a workaround might be:
#rest {
height: 100%;
padding-bottom: 200px;
}
The div itself will be too high, but because of the padding its content will have the right height.
you can do this with nested div tags. you have one specifying the width on the left, and then another left blank. To fill the rest of the other side you nest a 100% relative div inside the right side div. like so:
<div style="width:100%">
<div style="width:300px;background-color:#FFFF00;float:left">
</div>
<div style="margin-left:300px">
<div style="position:relative;left:0px;width:100%;background-color:#00FFFF">
</div>
</div>
</div>
Try
height: 100%;
or
height: auto;