Make an element scroll inside a grid section - html

I am trying to make a scrollable area inside my div like the image below. I want only the scrollable area to change height on different screen heights and scrolls accordingly.
The problem, is if the scrollable content is big enough to scroll, it will make the whole page scroll. If its small, the footer stays at the bottom correctly.
Here is a what I have so far
* {
margin: 0;
padding: 0;
width: 100%;
}
.container {
display: grid;
grid-template-rows: auto 1fr auto;
height: 100vh;
}
.header {
height: 30px;
background-color: lightblue;
}
.footer {
height: 30px;
background-color: lightblue;
}
.content {
display: grid;
grid-template-rows: auto 1fr;
}
.profile {
height: 60px;
background-color: lightpink;
}
.tabs {
height: 20px;
background-color: lightgreen;
}
.scroller {
background-color: cyan;
height: 100%;
overflow-y: scroll;
}
.scrollable-content {
background-color: yellow;
width: 200px;
height: 600px;
margin: 0 auto;
position: relative;
}
span {
bottom: 0;
left: 0;
position: absolute;
}
<div class="container">
<div class="header">Header</div>
<div class="content">
<div class="profile">Profile</div>
<div class="tab-control">
<div class="tabs">Tabs</div>
<div class="scroller">
<div class="scrollable-content">scrollable content<span>end</span></div>
</div>
</div>
</div>
<div class="footer">Footer</div>
</div>
Any help is appriciated

It works if you set some elements to have overflow: hidden;. Set that for .container, .content, and .tab-control
.container, .content, .tab-control {
overflow: hidden;
}
You will have a small issue with the .scroller element, part of it will be covered by the footer.
To fix that, add this too:
.tab-control {
display: flex;
flex-direction: column;
}
.scroller {
flex: 100% 1 1;
}

Set a fixed height on scroller. 100vh = height of the browser - 140px (the cumulative height of all the other elements on the page)
Set overflow-y: auto on the bar you want to scroll and you can set the height of .scrollable-content to as big as you want.
.scroller {
background-color: cyan;
height: calc(100vh - 140px);
overflow-y: scroll;
}
.scrollable-content {
background-color: yellow;
width: 200px;
height: 600px;
margin: 0 auto;
position: relative;
overflow-y: auto;
}

Related

CSS flex-box, how do I make an item stretch smaller than the content in the cross-axis direction?

I'm trying to make a container with side-by-side divs, one item has a fixed width and the other item has a fixed height. However, the flexible-height div won't shrink below its contents.
.parent {
background: #f00;
display: contents;
}
.container {
background: #0f0;
width: 25vw;
display: flex;
}
.object {
background: #00f;
margin: 10px;
width: 100px;
flex-shrink: 0;
}
.object.flexes-main-axis {
flex-grow: 1;
flex-shrink: 1;
}
.object.sets-cross-axis-size {
height: 75px;
}
.object.shrinks-cross-axis-below-content {
overflow-y: auto;
}
.child {
background: #f0f;
height: 100px;
width: 100px;
}
<div class='parent'>
<div class='container'>
<div id="object1" class='object flexes-main-axis sets-cross-axis-size'></div>
<div id="object2" class='object shrinks-cross-axis-below-content'>
<div class="child"></div>
</div>
</div>
</div>
I'm trying to get object2 to shrink and show a vertical scroll bar when I shrink object1 below 100px. The magenta box represents fixed-height content I can’t shrink, while object1 represents the element I want to control the container’s height.
The blue is hardcoded 75px tall, while the magenta is hardcoded 100px.
As the main .container has no height set it will grow to fit the tallest child. A main .container with a fixed height: ..px would still not make .child shrink. That's Flexbox.
But, if you set the .child to height: 100% and you will see it shrink:
* { outline: 1px dashed } /* for debugging */
.parent {
background: #f00;
display: contents;
}
.container {
background: #0f0;
width: 25vw;
display: flex;
}
.object {
background: #00f;
margin: 10px;
width: 100px;
flex-shrink: 0;
}
.object.flexes-main-axis {
flex-grow: 1;
flex-shrink: 1;
}
.object.sets-cross-axis-size {
height: 75px;
}
.object.shrinks-cross-axis-below-content {
overflow-y: auto;
}
.child {
background: #f0f;
height: 100%; /* Changed from 100px */
width: 100px;
}
<div class='parent'>
<div class='container'>
<div id="object1" class='object flexes-main-axis sets-cross-axis-size'>1</div>
<div id="object2" class='object shrinks-cross-axis-below-content'>
<div class="child">2</div>
</div>
</div>
</div>
So, I figured it out. I needed to add an extra wrapper div between object2 and child with height set to 0. Object2 will scroll to accommodate child overflow, but child's height won't count toward object2's content as far as the flexbox is concerned. Now as you change object1's height below child's height, you'll get a scroll bar in object2.
Also in this version, I made object1 responsive to the viewport width, so you can try it out by resizing the browser window.
.container {
display: flex;
background-color: red;
padding: 10px;
width: 50vw;
}
.sizecontroller {
aspect-ratio: 16 / 9;
background-color: blue;
padding: 10px;
flex-grow: 1;
flex-shrink: 1;
align-self: flex-start;
}
.sizeresponsive {
overflow-y: auto;
background-color: green;
padding: 10px;
flex-grow: 0;
flex-shrink: 0;
}
.sizeeraser {
height: 0;
background-color: purple;
padding: 10px;
}
.sizefixed {
width: 25px;
height: 250px;
background-color: yellow;
padding: 10px;
}
<div class="container">
<div class="sizecontroller"></div>
<div class="sizeresponsive">
<div class="sizeeraser">
<div class="sizefixed"></div>
</div>
</div>
</div>

height of div is not filling 100% body height

I have a sidebar a header and a main container. main container and header is nested inside a parent div. When I set height 100% for both sidebar and main container the sidebar doesn't take 100% of the height of the body. I was thinking to not use any percentage values and let flexbox do the work. But I suspect that as I append elements inside the main container area sidebar will behave the same and not take the height of the body space. How can I fix this?
html {
height: 100%;
}
body {
margin: 0;
}
.sidebar {
display: inline-flex;
min-height: 100vh;
}
.sidebar-container {
background-color: #00ffff;
width: fit-content;
}
.header_main {
display: inline-block;
position: absolute;
color: white;
}
.header {
background-color: black;
width: 100vw;
}
.main {
height: 100vh;
width: 100vw;
background-color: bisque;
}
<div class="sidebar">
<div class="sidebar-container">sidebar</div>
</div>
<div class="header_main">
<div class="header">header</div>
<div class="main">main</div>
</div>
Easiest way would be to use CSS-Grid. Then simply set the body as grid-container and give it a min-height: 100vh:
body {
margin: 0;
min-height: 100vh;
display: grid;
grid-template-columns: min-content auto;
grid-template-rows: min-content auto;
}
aside {
width: fit-content;
background-color: #00ffff;
grid-row: 1 / -1;
}
header {
background-color: pink;
}
main {
background-color: bisque;
}
<aside>Sidebar</aside>
<header>Header</header>
<main>Main</main>

Grid layout with only one column that scrolls

I want to create a layout where the left section stays in the same place and only the right side can be scrolled. But when I use position: fixed; the left section becomes full width and height of the viewport.
.container {
position: relative;
margin: 0;
padding: 0;
width: 100%;
display: grid;
grid-template-columns: 40% 60%;
}
.left {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-color: red;
}
.right {
height: 200vh;
background-color: blue;
}
<div class="container">
<div class="left">
</div>
<div class="right">
</div>
</div>
I created a right content, this make a overflow in right parent div.
*{
margin: 0;
padding: 0;
}
.container {
position: relative;
margin: 0;
padding: 0;
width: 100%;
height: 100vh;
display: grid;
grid-template-columns: 40% 60%;
}
.left {
/*position: fixed;
top: 0;
left: 0;*/
/* height: 100%;
width: 100%;*/
background-color: red;
}
.right {
overflow-y: scroll;
height: 100vh;
background-color: blue;
}
.right_content{
height: 200vh
}
<div class="container">
<div class="left">
LEFT
</div>
<div class="right">
<div class="right_content">RIGHT</div>
</div>
</div>
I played with it.
If you set your positions on the right and left classes to "inline" then the boxes will just be put in the container div following each other as you want them to. With fixed it will put it at 0,0 as you specifid but I think outside the workflow and your second div is inheriting from its parent div and using position relative so it also is at 0,0 (it has no position statement.
Also change your left height to "100vh". At 100% since the right one is at "200vh" it stretches out to be 200vh also.
so your code will look like this
#container {
display: grid;
position: relative;
margin: 0;
padding: 0;
width: 100%;
grid-template-columns: 40% 60%;
}
#left {
position: inline;
height: 100vh;
background-color: red;
}
#right {
position: inline;
height: 200vh;
background-color: blue;
}
There is an easy way to achieve what you want using flex-box. The only thing that you have to do is to wrap your content of the right side into an element with a defined height and the css style overflow-y: scroll;
body {
margin: 0;
padding: 0;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
}
.left {
height: 100%;
width: 40%;
background-color: red;
}
.right {
height: 100%;
overflow-y: scroll;
width: 60%;
background-color: blue;
}
.right-content {
height: 200vh;
}
<div class="container">
<div class="left">
left content
</div>
<div class="right">
<div class="right-content">
right content
</div>
</div>
</div>

CSS | Overflow child element with width 100%

The Problem
First of all: codepen
body, html width and height = 100%
body, html {
width: 100%;
height: 100%;
}
I have parent div with width 100% and height 100% out of body, and body out of html
.p {
width: 100%;
height: 100%;
background: green;
overflow-x: scroll;
display: flex;
flex-direction: row;
}
Then:
I have 2 child elements with both height 100% and width 20% + 80% and overflow-x: scroll
.c1 {
height: 100%;
width: 20%;
background: red;
overflow-x: scroll;
}
.c2 {
height: 100%;
width: 80%;
background: blue;
overflow-x: scroll;
}
I do not understand why scroll is showing up?
Change overflow: scroll; to overflow: auto
Remove, overflow-x: scroll
overflow-x: scroll property always show the scrollbar even if all content fits and you cant scroll it.
body, html {
width: 100%;
height: 100%;
margin: 0px;
}
.p {
width: 100%;
height: 100%;
background: green;
display: flex;
flex-direction: row;
}
.c1 {
height: 100%;
width: 20%;
background: red;
}
.c2 {
height: 100%;
width: 80%;
background: blue;
}
<div class="p">
<div class="c1"></div>
<div class="c2"></div>
</div>
Please Run the Above Snippet

Flexbox: shrink image to fit

I am trying to design a page with the following properties that will be used as digital signage:
Page height is viewport height (100vh) so that scrolling is impossible
Page is arranged into full-width rows
All rows but the last are static (have pre-defined content)
Last row (which will contain an image slideshow) should fill the remaining space in the viewport.
Here is what I have so far:
body {
margin: 0;
}
div#container {
display: flex;
flex-direction: column;
height: 100vh;
}
div.red {
height: 100px;
background-color: red;
flex: 0 0 auto;
}
div.blue {
height: 150px;
background-color: blue;
flex: 0 0 auto;
}
div.green {
background-color: green;
flex: 0 1 auto;
}
img {
max-height: 100%;
}
<div id="container">
<div class="red"></div>
<div class="blue"></div>
<div class="green">
<img src="http://lorempixel.com/200/300/">
</div>
</div>
https://jsfiddle.net/62qqnx3m/6/
Clearly this is not working because flex is not shrinking the image div to the right size.
I can remove the flex: 0 0 auto from the first two divs, but then they shrink instead.
How can I force the green div/image to take up exactly what space remains, no more, no less?
So if a taller image was supplied, it would shrink even more to fit.
And if an image is smaller than the available space, it should simply display, with the background div still filling the available space.
It seems like max-height:100% would be great for this, but that also does not work.
Furthermore, I have seen examples of how to do this horizontally (which I also need, but am having less trouble with), but I can't figure out how to translate that into vertical scaling.
You can set the position of the green block to relative and the position of the image to absolute.
Also make sure the height of the green block is set to 100% (to take the rest of the height of the page).
This should fix the problem:
body {
margin: 0;
}
div#container {
display: flex;
flex-direction: column;
height: 100vh;
}
div.red {
height: 100px;
background-color: red;
flex: 0 0 auto;
}
div.blue {
height: 150px;
background-color: blue;
flex: 0 0 auto;
}
div.green {
background-color: green;
flex: 0 1 auto;
position: relative;
height: 100%;
}
img
{
max-height: 100%;
position: absolute;
}
<body>
<div id="container">
<div class="red"></div>
<div class="blue"></div>
<div class="green"><img src="http://lorempixel.com/200/300/"></div>
</div>
</body>
So here's what we know:
The page height is 100vh
The first row is static (height: 100px)
The second row is static (height: 150px)
The third row, which contains images, should fill the remaining height
I think the solution lies in basic math:
100vh - 100px - 150px = height of third row
Instead of this in your code:
div.green {
background-color: green;
flex: 0 1 auto;
}
img {
max-height: 100%;
}
Try this:
div.green {
background-color: green;
flex: 1 1 auto;
}
img {
height: calc(100vh - 250px);
}
body {
margin: 0;
}
div#container {
display: flex;
flex-direction: column;
height: 100vh;
}
div.red {
height: 100px;
background-color: red;
flex: 0 0 auto;
}
div.blue {
height: 150px;
background-color: blue;
flex: 0 0 auto;
}
/*
div.green {
background-color: green;
flex: 0 1 auto;
}
img
{
max-height: 100%;
}
*/
div.green {
background-color: green;
flex: 1 1 auto;
}
img {
height: calc(100vh - 250px);
}
<div id="container">
<div class="red"></div>
<div class="blue"></div>
<div class="green">
<img src="http://lorempixel.com/200/300/">
</div>
</div>
revised fiddle
I just change the img class and add to class .green min-height: 100%; Additionally the image is responsive now with that code.
body {
margin: 0;
}
div#container {
display: flex;
flex-direction: column;
height: 100vh;
}
div.red {
height: 100px;
background-color: red;
flex: 0 0 auto;
}
div.blue {
height: 150px;
background-color: blue;
flex: 0 0 auto;
}
div.green {
background-color: green;
flex: 0 1 auto;
min-height: 100%;
}
.green img {
max-width: 100%;
display: block;
margin: 0 auto;
height: auto;
}
<body>
<div id="container">
<div class="red"></div>
<div class="blue"></div>
<div class="green"><img src="http://lorempixel.com/200/300/"></div>
</div>
</body>
Try this fiddle: https://jsfiddle.net/ez4pf8wp/
Added this to the img class:
img {
max-height: 100%;
height: 100%;
display: block;
margin: 0;
}