Let me first try to illustrate the problem
I have a webpage which contains a header and a sidenav. The sidenav is fixed in css, since I don't its content to move when scrolling.
When the page isn't scrolled down it works as intended, somewhat like this
However when I scroll i don't want whitespace on top of the sidenav. Currently when I scroll down the page, it looks somewhat like this
The intended behavior should be something like this
How do I go about this in css? Do I mess with the z-index of the elements? so the sidenav is behind the header when the page isn't scrolled? Or do I dynamically add to the sidenav's size when scrolling?
And how would either of these options be done in css?
As I understand, you have to set z-index of the header higher than the sidenav
Stack Snippet
.header {
height: 100px;
background: #000000;
position: relative;
z-index:999;
}
body {
margin: 0;
}
.sidebar {
position: fixed;
left: 0;
top: 0px;
width: 100px;
background: red;
height: 100%;
padding-top:100px;
}
.content {
height: 1000px;
background: yellow;
}
<div class="header"></div>
<div class="main">
<div class="sidebar"></div>
<div class="content"></div>
</div>
Related
Is it possible with only CSS to have the following effect:
I have two divs. One follows the other.
Now, if the user starts scrolling down the page (to see other content, more divs if you want..) the second div should "go up" (could also stay fixed and the first div goes down, I mean it would look the same) and overlap the first.
But only overlap for let's say 50px. After that, the behaviour is normal again, meaning that if you scroll further, those divs move out of the browser window eventually.
Have I made myself clear? I can add two coloured boxed to showcase if that helps. I played around a bit and tried parallex/position fixed/sticky mixes, but none seem to work with a given height restriction. I just wonder if this is possible without javascript.
You can get this effect by using position: sticky on both elements. There are a few things that can stop this from taking place, like having overflow: hidden or not having a height set on the parent element.
HTML
<div class="container">
<div class="red-box">This is the red box</div>
<div class="blue-box">this is the blue box</div>
</div>
<!-- needs space to be able to actually scroll on the page -->
<div class="container">
<div class=""></div>
<div class=""></div>
</div>
CSS
/* set the height of the container so that the sticky elements know how far they are meant to scroll */
.container{
min-height: 400px;
}
/* set your position sticky and a attribute that tells it when it should become sticky, in this case right at the top */
.red-box{
height: 400px;
background-color: red;
position: sticky;
top: 0px;
}
.blue-box{
height: 400px;
background-color: blue;
position: sticky;
top: 0px;
}
I have done a quick codepen example so that you can see this working. hope that helps.
https://codepen.io/Domnewmarch/pen/NWzqBde
Solution: I used a combination of negative margin, z-index and position: sticky.
Added margin to the 2nd container to make it more visible.
.sticky-wrapper {
height: 310px;
margin-bottom: -60px;
}
.content {
z-index: -1;
position: sticky;
top: 0;
padding: 0 3%;
height: 250px;
background-color: green;
}
.foo {
margin: 0 50px;
background-color: red;
height: 200px;
}
.next-content {
height: 1000px;
background-color: khaki;
}
<div class="sticky-wrapper">
<div class="content"></div>
</div>
<div class="foo"></div>
<div class="next-content"></div>
In my website I have two main divs - one for the banner at the top, and one for the main content. They both contain inner elements like imgs, iframes etc. but I don't think this is important for my problem which is: how can I make the scroll bar for the main content not overlap the banner?
If it helps, you can view the source for my actual website on my github. But to save wasting time looking, I've wrote a small snippet in html which demonstrates this issue:
document.getElementById("someText").innerText = "this is some content ".replace(/ /g, '\n').repeat(15);
html, body {
margin: 0;
padding: 0;
}
#header {
position: fixed;
background-color: teal;
z-index: 1;
top: 0;
height: 100px;
width: 100%;
}
#main {
postion: absolute;
top: 100px;
}
<body>
<div id="header">
header
</div>
<div id="main">
<pre id="someText"></pre>
</div>
</body>
It may be hard to see, in the snippet here on SO but the scroll bar on the right overlaps the banner and I what I want is for it to stop when it reaches the banner.
I have tried (in the CSS) setting the overflow of the body to hidden as this is the scroll bar overlapping the banner, but this just removes it entirely so I can't scroll - so clearly not what I am looking for...
I have also tried setting the overflow-y of the main div to scroll, but this does not work as a bar does appear where I want it, but it is grayed-out so not usable.
I have created a fiddle for you:
https://jsfiddle.net/3gvowvag/1/
Your HTML and JS stays the same. For your CSS:
html, body {
margin: 0;
padding: 0;
overflow-y: hidden;
}
#header {
position: fixed;
background-color: teal;
z-index: 1;
top: 0;
height: 100px;
width: 100%;
}
#main {
position: absolute;
top: 100px;
max-height: 100%;
width: 100%
overflow-y: scroll;
}
So the changes are basically to give your html, body a overflow-y: hidden and your #main a max-height and width of 100% as well as overflow-y: scroll.
This basically does what you want - though I wouldn't be 100% confident about setting up the page like that. Absolute positioning and offsetting via pixels is a bit oldschool, also setting the overflow-y to hidden for html/body, not exactly sure how those things will behave in the long term. But pretty hard to fully think of this without further context.
P.S.: awesome cat!
You just need to add overflow-y: hidden; to the body (take a look at this previous answer) and then apply overflow-y: scroll; to the #main div.
document.getElementById("someText").innerText = "this is some content ".replace(/ /g, '\n').repeat(30);
html, body {
margin: 0;
padding: 0;
}
body {
overflow-y: hidden;
}
#header {
position: fixed;
background-color: teal;
z-index: 1;
top: 0;
height: 100px;
width: 100%;
}
#main {
postion: absolute;
top: 100px;
overflow-y: scroll;
}
<body>
<div id="header">
header
</div>
<div id="main">
<pre id="someText"></pre>
</div>
</body>
You might find this easier with a flexbox layout. Maybe something like this. As example set the overflow to auto if you don't want to see the greyed out scroll bar
<div class="wrapper">
<div class="header">
header
</div>
<div class="content">
content
content
content
</div>
</div>
.wrapper{
display:flex;
flex-direction:column;
background:blue;
height: 100vw;
}
.header{
height:100px;
background-color:pink
}
.content{
background:green;
flex-grow: 1;
overflow:scroll;
}
Here is the html:
<body>
<div class="ngdialog">
<div class="ngdialog-overlay></div>
<div class="ngdialog-content>
...modal content
</div.
</div>
<body>
The ngdialog div is, as you can guess, an modal (z-index: 10000).
My goal is, by applying some comination of styles (position, float etc.) to the elements to make it so that:
a) When the modal is displayed, have the overlay (grey and opacity; 0.5) cover all other elements in the page.
b) If the modal content is longer than the page, I would like the user to be able to use the main scroll bar to see the bottom/top of the modal. In other words, if the rest of the page is only 100px but the modal is 200px, I would like the scoll bar to allow the user to scroll that extra 100px.
The issue I am having is that when I position ngdialog as absolute, the window won't allow me to scroll to see the rest of the modal (as the absolute element is no longer in the standard element flow).
If I try to use fixed positioning, there is no scroll bar. If I use relative positioning, the other page elements (which the overlay is above) get moved around.
I have tried (what feels like) every combination of absolute, relative, fixed, static, float on all of these elements and I can't get the behavior I am seeking.
Keep in mind that body is position: relative (this can be changed if need be).
Thanks in advance, appreciate all comments.
Edit: Sorry, I had to go to sleep there, here is a fiddle:
https://jsfiddle.net/vpgoy756/1/
WIthout changing your HTML structure, this is what you'd need to do:
* {
/* This was to save typing */
margin: 0;
padding: 0;
}
html {
width: 100%;
height: 100%;
}
body {
position: relative;
width: 100%;
min-height: 100%;
}
.ngdialog {
z-index: 10000;
text-align: center;
overflow: hidden;
}
.ngdialog-overlay {
position: absolute;
width: 100%;
height: 100%;
z-index: 9999;
background: rgba(0,0,0, .4);
}
.ngdialog-content {
position: absolute;
z-index: 10000;
width: 100%;
height: 100%;
max-height: 100%;
overflow: auto;
}
.panel {
margin-top: 50px;
margin-left: 10%;
margin-right: 10%;
min-height: 500px;
z-index: 10000;
}
.reg-page-block {
width: 200px;
height: 200px;
display: inline-block;
background-color: #0f0;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<!-- ^ from your provided fiddle -->
<body>
<div class="ngdialog">
<div class="ngdialog-overlay"></div>
<div class="ngdialog-content">
<div class="panel panel-primary">
<div class="panel-heading">modal</div>
<div class="panel-body">content</div>
</div>
</div>
</div>
<div class="reg-page-block">Regular Page</div>
</body>
Be aware that if both the dialog and content are taller than the viewport, you will get double scrollbars - this may not be desirable but you specifically asked for the dialog to scroll separately from the content.
Try some of this CSS and see if it does the trick. It's hard to provide an exact solution without seeing your current CSS code, but maybe this will work.
Use this HTML structure instead:
<div class="ngdialog-overlay">
<div class="ngdialog-content">CONTENT HERE</div>
</div>
And this CSS code:
.ngdialog-overlay {
display:block;
width:100%;
height:100%;
background:#333333;
background:rgba(0,0,0,0.8);
z-index:10000;
position:fixed;
top:0;
left:0;
overflow: scroll;
}
.ngdialog-content{
text-align: center;
width:100%;
height:100%;
padding-top:30px;
padding-bottom:30px;
/* Optional if you want content vertically centered */
display:table-cell;
vertical-align: middle;
}
The trick is overflow:scroll; and height:100%; - because we have a set height, if the contents become any taller than that they will overflow and scroll. But in this case, when the user tries to scroll it will actually be scrolling the .ngdialog-overlay element and not the window itself.
http://jsfiddle.net/bcole808/6wcsxf3z/1/
In CSS file Add below lines
.modal-dialog {
transform: translateY(50%)!important;
}
You can change 50% to any other value which will solve problem in your Browser
It worked for me
I have the following layout:
On the left side I have a menu and big gray part on the right side is the body content. The problem is on the left menu I have a bunch of buttons. I want this menu to be fixed position and body scrollable. I Have the following css:
#menu {
position: fixed;
}
#content {
position: inherit;
margin-left:300px;
}
The problem is that on the red part of my menu all button unavailable, I can't click on it. looks like body overrides the menu.
Any ideas what the problem might be?
Thanks
Including the html would give a better sense of the stacking order and likely yield a better answer. Given what you've provided, this should fix:
#menu {
position: fixed;
z-index: 1;
}
In order to fix it to the top and not scroll, you don't use position: fixed;. You need to use position: absolute;. If you don't want it at the very top, then you use position: relative; and place it inside an element.
Then, in order to scroll, you use position: fixed;.
When you use position: fixed, it places the element fixed within the visible page.
However, when you use position: absolute, what this does is put it on an absolute position on the page regardless of scroll. For example, if you added the css top:0; then it would be 0 pixes from the absolute top of page, and if you scroll down it will disappear from view because it is all the way at the top of the actual page, not just the top of the visible page.
I understand it seems a bit counter-intuitive to you. However, you can see it working in the jsbin below.
Working jsbin:
http://jsbin.com/Uwuyuha/1
page.html
<body>
<div id="container">
<div id="menu">
1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br>10<br>
</div>
<div id="content">
</div>
</div>
</body>
style.css
body {
width: 100%;
height: 100%;
}
#container {
width: 1000px;
height: 1000px;
}
#menu {
width: 250px;
height: 2000px;
position: fixed;
background: #999;
}
#content {
width: 650px;
height: 300px;
position: absolute;
margin-left: 251px;
background: #444;
}
I am experiencing some strange behaviour when attempting the following (see jsfiddle: http://jsfiddle.net/9nS47/).
HTML:
<div id="slider">
<div id="wrapper">
<div id="navigation"></div>
<div id="container">
<div id="button"></div>
</div>
</div>
</div>
CSS:
HTML,BODY
{ width:100%; height:100%; }
* { margin: 0; padding: 0; }
#slider
{
position: fixed;
top: 0;
bottom: 0px;
left: 100px;
overflow-y: auto;
background-color: red;
}
#wrapper
{
position: relative;
height: 100%;
background-color: #000000;
min-height:400px;
}
#navigation
{
display: inline-block;
width: 80px;
height: 100%;
background-color: #0000FF;
}
#container
{
display: inline-block;
height: 100%;
background-color: #00FF00;
}
#button
{
width: 22px; height: 100%;
float:right;
background-color: #CCFFCC;
cursor:pointer;
}
What I am trying to do is making a left side navigation bar that spans the whole visible window height and only Shows a scrollbar if its height is smaller than for example 400px. The scrollbar for that div seems to be always visible due to some resizing problems (there is an extra pixel at the bottom I can't explain[color:red]).
Firefox also moves the second child element below the first when the scrollbar is visible because the scrollbar seems to be part of the content area and thus takes up to around 20px space. This does not happen if Overflow: Auto is replaced with Overflow: scroll however.
ATM changing the layout (specifically the Container with Position: fixed) is not an option.
Don't mind the space between the green and the blue box. Seems to be a whitespace problem.
Since it seems like you are unable to change your 'wrapper' code much, I tried to change your original code as little as possible. In fact, the only thing I did was to add some jQuery.
Check out this updated jsfiddle. I have included jQuery and the javascript I added was this:
$(window).bind("load resize", function(){
//this runs as soon as the page is 'ready'
if($(window).height() < 400){
$("#slider").css("overflow-y","scroll");
}else{
$("#slider").css("overflow-y","hidden");
}
});
Basically, 'onload' and 'onrezise', the jQuery figures out if you should show the scrollbars or not.
The reason that your "auto" isn't working is because of the "fixed" position of the slider element. The browser cannot perfectly figure out the heights.