HTML/CSS: scroll div without setting position to fixed or absolute
I think I found a solution for you:
Wrap contents of sidebar into second div and add some class attribute - .fixed in my example. Now, we make .fixed div fixed, .sidebar div will take the space, so .content won't be overlapped by .fixed. Remember to set the same width for .fixed and .content, so they take the same space . Now, set width: auto
in .content div, so it take all the space and overflow: hidden
.
Now, when .sidebar has display: none
, fixed will be hidden, and .content will take all their space :D
CSS:
div.sidebar {
/* take space on the left */
float:left;
width:20%;
margin-bottom:100%;
background-color:rgb(0, 0, 0);
}
div.fixed {
/* display fixed menu */
position:fixed;
width:20%;
left:0rem;
top:0rem;
bottom:1.2rem;
z-index:999;
rgb(110, 110, 110)
overflow-y:scroll;
}
div.content {
width:auto; /* take all the space */
overflow:hidden; /* try using without it and see what happens ;) */
border-width: 0;
background-color: transparent;
font-size: 180%;
line-height: 130%;
}
Working example: http://jsfiddle.net/z8dqhrf2/2/
Make fixed position div scrollable without scrollbar and without scrolling the background content
This is ugly but it works
.mobile_menu
{
//...
height: 100%;
overflow: scroll;
right: -25px;
}
https://jsfiddle.net/sk9dhgbj/
Have a fixed position div that needs to scroll if content overflows
The problem with using height:100%
is that it will be 100% of the page instead of 100% of the window (as you would probably expect it to be). This will cause the problem that you're seeing, because the non-fixed content is long enough to include the fixed content with 100% height without requiring a scroll bar. The browser doesn't know/care that you can't actually scroll that bar down to see it
You can use fixed
to accomplish what you're trying to do.
.fixed-content {
top: 0;
bottom:0;
position:fixed;
overflow-y:scroll;
overflow-x:hidden;
}
This fork of your fiddle shows my fix:
http://jsfiddle.net/strider820/84AsW/1/
How can I make the contents of a fixed element scrollable only when it exceeds the height of the viewport?
You probably can't. Here's something that comes close. You won't get content to flow around it if there's space below.
http://jsfiddle.net/ThnLk/1289
.stuck {
position: fixed;
top: 10px;
left: 10px;
bottom: 10px;
width: 180px;
overflow-y: scroll;
}
You can do a percentage height as well:
http://jsfiddle.net/ThnLk/1287/
.stuck {
max-height: 100%;
}
Scrolling div without fixed height
You could stretch the div using absolute positioning. This way it will always take the size of the browser window (or the closest positioned ancestor).
Given this HTML:
<div id="gridcontainer"></div>
the CSS should be something like:
#gridcontainer {
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
overflow: auto;
}
Live Demo
Prevent body scrolling but allow overlay scrolling
Theory
Looking at current implementation of the pinterest site (it might change in the future), when you open the overlay, a noscroll
class is applied to the body
element (setting overflow: hidden
) making the body
no longer scrollable.
The overlay created on-the-fly or already injected in the page and made visible via display: block
— it makes no difference – has position : fixed
and overflow-y: scroll
, with top
, left
, right
and bottom
properties set to 0
: this style makes the overlay fill the whole viewport (but now we are in 2022, so you may use inset: 0
instead).
The div
inside the overlay is in position: static
so the vertical scrollbar is related to that element. This is resulting in a scrollable but fixed overlay.
When you close the overlay, you have to hide it (using display: none
) and you could even remove the node via javascript (or just the content inside, it's up to you but also depends on the nature of the content).
The final step is to also remove the noscroll
class applied to the body
(so the overflow
property gets back to the value it had previously)
Code
Codepen Example
(it works by changing the aria-hidden
attribute of the overlay in order to show and hide it and to increase its accessibility).
Markup
(open button)
<button type="button" class="open-overlay">OPEN LAYER</button>
(overlay and close button)
<section class="overlay" aria-hidden="true" tabindex="-1">
<div>
<h2>Hello, I'm the overlayer</h2>
...
<button type="button" class="close-overlay">CLOSE LAYER</button>
</div>
</section>
CSS
.noscroll {
overflow: hidden;
}
.overlay {
position: fixed;
overflow-y: scroll;
inset: 0; }
[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }
Javascript (vanilla-JS)
var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]'),
openingBtt;
[].forEach.call(overlayBtts, function(btt) {
btt.addEventListener('click', function() {
/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';
/* storing a reference to the opening button */
if (overlayOpen) {
openingBtt = this;
}
/* Toggle the aria-hidden state on the overlay and the
no-scroll class on the body */
overlay.setAttribute('aria-hidden', !overlayOpen);
body.classList.toggle('noscroll', overlayOpen);
/* On some mobile browser when the overlay was previously
opened and scrolled, if you open it again it doesn't
reset its scrollTop property */
overlay.scrollTop = 0;
/* forcing focus for Assistive technologies but note:
- if your modal has just a phrase and a button move the
focus on the button
- if your modal has a long text inside (e.g. a privacy
policy) move the focus on the first heading inside
the modal
- otherwise just focus the modal.
When you close the overlay restore the focus on the
button that opened the modal.
*/
if (overlayOpen) {
overlay.focus();
}
else {
openingBtt.focus();
openingBtt = null;
}
}, false);
});
/* detect Escape key when the overlay is open */
document.body.addEventListener('keyup', (ev) => {
if (ev.key === "Escape" && overlay.getAttribute('aria-hidden') === 'false') {
overlay.setAttribute('aria-hidden', 'true');
body.classList.toggle('noscroll', false);
openingBtt.focus();
openingBtt = null;
}
})
Finally, here's another example in which the overlay opens with a fade-in effect by a CSS transition
applied to the opacity
property. Also a padding-right
is applied to avoid a reflow on the underlying text when the scrollbar disappears.
Codepen Example (fade)
CSS
.noscroll { overflow: hidden; }
@media (min-device-width: 1025px) {
/* not strictly necessary, just an experiment for
this specific example and couldn't be necessary
at all on some browser */
.noscroll {
padding-right: 15px;
}
}
.overlay {
position: fixed;
overflow-y: scroll;
inset: 0;
}
[aria-hidden="true"] {
transition: opacity 1s, z-index 0s 1s;
width: 100vw;
z-index: -1;
opacity: 0;
}
[aria-hidden="false"] {
transition: opacity 1s;
width: 100%;
z-index: 1;
opacity: 1;
}
Scrollbar without fixed height/Dynamic height with scrollbar
Flexbox is a modern alternative that lets you do this without fixed heights or JavaScript.
Setting display: flex; flex-direction: column;
on the container and flex-shrink: 0;
on the header and footer divs does the trick:
HTML:
<div id="body">
<div id="head">
<p>Dynamic size without scrollbar</p>
<p>Dynamic size without scrollbar</p>
<p>Dynamic size without scrollbar</p>
</div>
<div id="content">
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
<p>Dynamic size with scrollbar</p>
</div>
<div id="foot">
<p>Fixed size without scrollbar</p>
<p>Fixed size without scrollbar</p>
</div>
</div>
CSS:
#body {
position: absolute;
top: 150px;
left: 150px;
height: 300px;
width: 500px;
border: black dashed 2px;
display: flex;
flex-direction: column;
}
#head {
border: green solid 1px;
flex-shrink: 0;
}
#content{
border: red solid 1px;
overflow-y: auto;
/*height: 100%;*/
}
#foot {
border: blue solid 1px;
height: 50px;
flex-shrink: 0;
}
Positioning div outside of overflow scroll without using absolute positioning?
If you overlap the #leftCol
with the #rightCol
(by positioning them absolute
to left:0;
of their parent container), set the left margin to the width of the left column, then set .content
position to relative
and box position to absolute
, and adjust the positioning using left
.
Here is the updated CSS:
#leftCol{
position:absolute;
width: 100px;
height: 500px;
background: green;
left:0;
}
#rightCol{
position:absolute;
padding-left:100px;
width: 400px;
height: 500px;
overflow-y: scroll;
left:0;
}
.content{
height: 700px;
width: 100%;
background: red;
position:relative;
}
.box{
width: 100px;
height: 100px;
background: purple;
position:absolute;
left:-100px;
}
and a DEMO
Hope this helps =)
Related Topics
How to Have a Horizontal Multiple Colour Gradient on Text Using CSS3/HTML 5
Removing Page Scrollbars in IE8 (Overflow:Hidden Not Working)
Box-Shadow Only on Left and Right
What Does a Space Preceding :Nth-Child(N) Do
Is It Posible to Make an Input Checkbox a Bootstrap Glyphicon
Filter: Blur Not Working on Ms Edge
Css-Moving Text from Left to Right
Selector for All a Tag Descendants
Element Opacity But Not Border
How to Layer Box-Shadows Using Z-Index
Safari Page-Break-Inside:Avoid Not Working
Style Type="Text/Css" ... What Else Is There
Bootstrap 4 Center Navbar Brand with Collapse
How to Vertically Center Text in Its Bounding Box
How to Get CSS Variables Working in Chrome 34
Why an Inline-Block Container Doesn't Collapse When Contains Only Floated Items
CSS Pointer-Events and Appearance Properties Not Recognized by CSS Validator