Make div in div in div scrollable with overflow - html

I have an React application and having a slightly bigger problem with some CSS stuff.
I have an view which is divided in 2 parts. But those two parts are lying in one bigger component. The left part is displaying some contacts and on the right I want to display details of those contacts. Now I want to make the left part scrollable like a list, but the right part just stay fixed on its position. Also the height of the left part should always stay as high as the current screen size. I am using Bulma CSS as my base CSS framework.
This is my HTML:
<div class="pane main-content" id="mainPane">
<div class="contacts-view">
<h1 class="title">My Title</h1>
<div class="">Other Stuff</div>
<div class="columns">
<div class="column is-3">
<div class="columns is-multiline">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
</div>
<div class="column is-9"></div>
</div>
</div>
</div>
This is a quick sketch of how it looks:
Current relevant CSS:
.main-content {
background-color: #fff;
padding: 20px;
}
.pane {
position: relative;
overflow-y: auto;
flex: 1;
}
.columns {
margin-left: -0.75rem;
margin-right: -0.75rem;
margin-top: -0.75rem;
}
.column {
display: block;
-ms-flex-preferred-size: 0;
flex-basis: 0;
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
-ms-flex-negative: 1;
flex-shrink: 1;
padding: 0.75rem;
}
For better explanation. The component with class column is-3 should be scrollable but all other parts should stay fixed with no scroll.
I tried:
.is-3
overflow:hidden;
overflow-y:scroll;
But I found out that I have to set the height of is-3 because otherwise my screen is just expanded to the bottom. But I can not set a fixed height to it, because my screen size is dynamic and depended on the size of #mainPane. But I can also not set it to 100% because then the screen is also expanded at the bottom. Do you have any suggestions how I can solve this with CSS ?
Thanks in advance :)

You can use flexbox layout.
jsFiddle
body {
margin: 0;
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
.header {
background: lightblue;
}
.content {
flex: 1;
display: flex;
min-height: 0; /*ADDED 2021*/
}
.sidebar {
background: lightgreen;
overflow: auto;
}
.main {
flex: 1;
background: pink;
overflow: auto;
}
<div class="container">
<div class="header">header</div>
<div class="content">
<div class="sidebar">
<div style="height:200vh;">sidebar</div>
</div>
<div class="main">
<div style="height:200vh;">main</div>
</div>
</div>
</div>

Related

How do I fill the remainder of the visible page with a background color?

I have a page I'm trying fill some content with and then the remainder of the page fill with a background color. I've kind of been able to achieve this using min-height: 100vh but the problem is now my page scroll get's extended significantly. Is it possible just to color the visible space on the screen without increasing scrollable area on the page.
Here's a simple example with a jsfiddle:
If you remove the min-height: 100vh from .footer notice that the colored square gets much smaller and now the scroll area isn't very large either. How do I only fill that area that's visible when not using the min-height style.
.body {
margin-left: 50px;
}
.footer {
background-color: grey;
min-height: 100vh;
z-index: -100;
margin-top: -150px;
}
img {
z-index: 100;
margin-left: 200px;
}
h1 {
text-align: center;
}
<div class="body">
<div class="row justify-content-center text-centerr">
<h1>
This is my page heading
</h1>
</div>
<div class="row justify-content-center text-center">
<p>
This is some information about this page.
</p>
</div>
<div class="row justify-content-center text-centerr">
<div class="justify-content-center">
<img src="https://cdn.vox-cdn.com/thumbor/RkBHz5tPuCNQOG0a6FooNwiqQyw=/0x0:939x704/1820x1213/filters:focal(0x0:939x704):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/49610677/homersimpson.0.0.jpg"
width="300px"
height="300px"
</div>
</div>
<div class="footer">
<br />
</div>
</div>
This is what I came up with, using flexbox and flex-grow: 1 to force the element to grow and take up the remaining space and flex-shrink: 0 to prevent the img and other elements from shrinking.
I had to add a new class to he footer's parent element, to add the flexbox class to it. note the footer-parent class.
<div class="body">
<div class="row justify-content-center text-center">
<h1>
This is my page heading
</h1>
</div>
<div class="row justify-content-center text-center">
<p>
This is some information about this page.
</p>
</div>
<div class="row footer-parent justify-content-center text-center">
<div class="justify-content-center">
<img src="https://cdn.vox-cdn.com/thumbor/RkBHz5tPuCNQOG0a6FooNwiqQyw=/0x0:939x704/1820x1213/filters:focal(0x0:939x704):format(webp)/cdn.vox-cdn.com/uploads/chorus_image/image/49610677/homersimpson.0.0.jpg" width="300px" height="300px" />
</div>
<div class="footer">
<br />
</div>
</div>
</div>
Here's the CSS
body {
margin: 0;
}
.body {
display: flex;
flex-flow: column nowrap;
margin-left: 50px;
height: 100%;
min-height: 100vh;
}
.footer {
background-color: grey;
flex-grow: 1;
z-index: -100;
margin-top: -150px;
}
.footer-parent {
display: flex;
flex-grow: 1;
flex-flow: column nowrap;
}
img {
z-index: 100;
flex-shrink: 0;
margin-left: 200px;
}
h1 {
flex-shrink: 0;
text-align: center;
}

Dynamic size of footer with full screen web page

image wireframe
I would like to recreate messaging phone app in html and css. So the app must be full frame without any overflow.
The trick is the bottom part (in red) must be resizable according to the child content. So I used flex (with flex-direction: column) to manage my layout.
The problem is : when the content (in yellow) grow up, the core part will compress the red part. My goal is to overflow, with a scrollbar, the content inside the core part and don't change the size of the red div.
index.html
<body>
<div id="header">
</div>
<div id="core">
<div class="conainer" style="">
<div class="row">
<div class="two columns"></div>
<div class="ten columns">
<div class="msgright">
.
</div>
</div>
</div>
<div class="row">
<div class="ten columns">
<div class="msgright">
.
</div>
</div>
<div class="two columns"></div>
</div>
</div>
</div>
<div id="footer">
</div>
index.css
html, body, div {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
max-height: 100%;
overflow: hidden;
}
body {
display: flex;
flex-direction: column;
}
#header {
height: 50px;
background: #2A9D8F;
flex: 0 0 auto;
}
#core {
background-color: #264653;
flex: 1;
display: flex;
align-items: flex-end;
}
#footer {
height: auto;
background-color: red;
min-height: 50px;
flex: 0 0 auto;
}
.conainer {
flex: 0 0 100%;
}
.row {
margin: 5px;
background-color: yellow;
height: 130px;
}
https://codepen.io/jln_brtn/pen/pobVZBv
Best regards and thank you for your help.
I'm not sure if I understand the problem correctly but since your .row elements have a fixed height: 130px, the element should not be able to grow any further. Overflow styling to .row elements can be added like this:
.row {
overflow-y: scroll;
}
If it is just the #core element, then you can do something like this:
#core {
overflow-y: scroll;
}
For this instance I would suggest to use CSS Grid instead of Flexbox, and giving both <header> and <footer> the space they need, while the <main> gets the rest. This means that both <header> and <footer> stay were they are, even if <main> needs more space for its content, meaning <main> will get a scrollbar.
You can achieve the same by using position: fixed and setting a margin to top and bottom, with fixed heights of <header> and <footer>, and sizing <main> with height: calc(100% - HEIGHT_OF_HEADER - HEIGHT_OF_FOOTER). The problem with this is maintenance, as you would always have to check and revalidate the heights when changing something.
html, body {
margin: 0;
width: 100%;
height: 100%;
}
body {
display: grid;
grid-template-rows: auto 1fr auto;
}
header {
height: 3.125rem;
background: #2A9D8F;
}
main {
padding: 0.3125rem;
display: flex;
flex-flow: column;
gap: 0.3125rem;
background: #264653;
overflow: hidden auto;
}
footer {
height: 3.125rem;
background: red;
}
main > div {
flex-shrink: 0;
height: 8.125rem;
background: yellow;
}
<header></header>
<main>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</main>
<footer></footer>

How to use flexbox inside a fixed container?

I have a div that is position: fixed; within the viewport. Within this are a series of child elements that use display: flex; and I need a scrollable element to fill 100% of the height of the flexed element. The problem I am having is that because done of the parent elements of the scrollable element have a fixed height, so the scrollable element just pushed the bottom of the flexed element rather than scroll.
Please see the following JSBin example. In this example, the blue block needs to extend to 100% the height of the red block, with the contents of the blue block still being scrollable. Needs to work in IE10+, latest Firefox and Chrome:
https://jsbin.com/terimim/edit?html,css,output
There are two primary issues causing the layout problem. They are each explained here:
Why doesn't flex item shrink past content size?
Chrome / Safari not filling 100% height of flex parent
revised demo
* {
box-sizing: border-box;
min-height: 0;
}
body {
background-color: #eaeaea;
}
#menu {
background-color: #fff;
position: fixed;
top: 20px;
right: 20px;
left: 20px;
bottom: 20px;
padding: 0;
z-index: 12;
height: calc(100vh - 40px);
}
#menu-contents {
display: flex;
flex-direction: column;
height: 100%;
}
#menu-pane-wrapper {
display: flex;
flex: 1;
background-color: #eeffcc;
}
#menu-panes {
flex: 1;
display: flex;
}
.menu-pane {
box-sizing: border-box;
background-color: #ff0000;
width: 20%;
padding: 10px;
display: flex;
}
.menu-pane-overflow {
flex: 1;
overflow-x: hidden;
overflow-y: scroll;
background-color: aqua;
}
.menu-item {
padding: 5px;
}
<div id="menu">
<div id="menu-contents">
<div id="menu-header">HEADER</div>
<div id="menu-pane-wrapper">
<div id="menu-panes">
<div class="menu-pane">
<div class="menu-pane-overflow">
<div class="menu-pane-scroll">
<div class="menu-item">1</div>
<div class="menu-item">2</div>
<div class="menu-item">3</div>
<div class="menu-item">4</div>
<div class="menu-item">5</div>
<div class="menu-item">6</div>
<div class="menu-item">7</div>
<div class="menu-item">8</div>
<div class="menu-item">9</div>
<div class="menu-item">10</div>
<div class="menu-item">11</div>
<div class="menu-item">12</div>
<div class="menu-item">13</div>
<div class="menu-item">14</div>
<div class="menu-item">15</div>
<div class="menu-item">16</div>
<div class="menu-item">17</div>
<div class="menu-item">18</div>
<div class="menu-item">19</div>
<div class="menu-item">20</div>
<div class="menu-item">21</div>
<div class="menu-item">22</div>
<div class="menu-item">23</div>
<div class="menu-item">24</div>
<div class="menu-item">25</div>
<div class="menu-item">26</div>
<div class="menu-item">27</div>
<div class="menu-item">28</div>
<div class="menu-item">29</div>
<div class="menu-item">30</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

Style one single column with flexbox

Maybe I want something impossible.
I want a website with only a single column styled with flexbox. The purpose is that only one column stretches its height to the footer regardless the size of the content of the column. Something like below structure:
I try to reach that with this code (I am using bootstrap):
<div class="container-fluid">
<div class="row">
<header class="col-md-12">
stuff...
</header>
<div class="col-md-1 col-a">
stuff...
</div>
<div class="col-md-10 col-b">
Stuff...
</div>
<div class="col-md-1 col-c">
<div class="col-c-child">
Stuff..
</div>
</div>
<footer class="col-md-12">
Stuff
</footer>
</div>
</div>
And then adding in the CSS this specific for the col-c and col-c-child:
.col-c {
display: flex;
flex-direction: column;
height: 100%;
}
.col-c-child {
flex: 1;
}
But is not working.
Any idea?
THE SOLUTION:
Create a row for the header, other for the content and other for the footer, that is - don't have everything in the same row.
Build a div-wrapper englobing col-a, col-b and col-c with display:flex and flex-direction: row;
get rid of col-c-child
col-c with flex: 1;
Thanks to #jelleB who elucidated me for part of it.
Put the header and the footer in different rows.
You should build a div below col-a (without content)
Use min-height: 100% on the row where you put col-a/col-b/col-c in
Give this a shot
I suspect your problem lies in the height:100%
If I am not mistaken, you cannot do that unless the parent container has its height defined. If the parent container's height is also defined as a percentage then the parent's parent container's height must also be defined. This hierarchy continues up to the body tag.
If you are able to wrap your middle divs, you can do the following:
html,
body {
height: 100%;
padding: 0;
margin: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}
.container #body {
display: flex;
flex-direction: row;
flex-grow: 1;
}
header,
footer {
width: 100%;
}
.left,
.right {
width: 100px; /*change to whatever width you want*/
}
.center {
flex-grow: 1;
}
/*styles for demo*/
header,
footer {
height: 50px;
background: blue;
}
.left,
.right {
background: green;
}
.center {
background: red
}
<div class="container">
<header></header>
<div id="body">
<div class="left"></div>
<div class="center"></div>
<div class="right"></div>
</div>
<footer></footer>
</div>

Bootstrap: Change container order on small screens

I'm facing a bootstrap problem.
In my html page, I used different containers but I'm not able to re-arrange and re-organize them as I want in mobile screens.
Here my Bootply.
And to be more clear, I want it to look like this:
Containers 1 and 5 are fluid, instead 2, 3, 4 are not.
How can I move container 1 and 2 after 3 and 4 in small screens?
Thank you in advance for your reply!
Cheers!
This is not possible without rearranging your content.
One way is to make two versions of the area you want to rearrange and hide them based on the width of the browser. This is bad practice, especially if you have a whole website you want to rearrange on resize, but for a small div with 5 divs inside it would be an acceptable solution.
Here is the adapted HTML
<div class="desktopwrapper"> <!-- added a desktop wrapper -->
<div class="container-fluid green"></div>
<div class="container red"></div>
<div class="container ">
<div class="row">
<div class="col-sm-8 yellow"></div>
<div class="col-sm-4 fuxia"></div>
</div>
</div>
<div class="container-fluid blue"></div>
</div>
<div class="mobilewrapper"> <!-- added a mobile wrapper and rearranged content -->
<div class="container ">
<div class="row">
<div class="col-sm-8 yellow"></div>
<div class="col-sm-4 fuxia"></div>
</div>
</div>
<div class="container-fluid green"></div>
<div class="container red"></div>
<div class="container-fluid blue"></div>
</div>
And I have added these lines to CSS:
#media screen and (max-width: 766px) {
.desktopwrapper {
display:none;
}
}
#media screen and (min-width: 767px) {
.mobilewrapper {
display:none;
}
}
What this basically does, is hide one arrangement when the screen gets resized to 766px wide and will display the other. And of course the other way around.
You can try it out here.
Another way would be to put everything in a wrapper, position the wrapper relative, all the divs inside absolute and just place them with using px. This is however really not useful when divs have changing heights depending on the content. The best way would be to do like the example I have.
flexbox proof of concept.
* {
margin: 0;
padding: 0;
}
html {
height: 100%;
color: white;
text-align: center;
}
body {
height: 100%;
}
h2 {
display: inline-block;
background: #000;
padding: .25em;
}
.page {
min-height: 100%;
display: flex;
flex-direction: column;
}
header {
flex: 0 0 75px;
background: darkgreen;
}
.banner {
flex: 0 0 100px;
width: 80%;
margin: auto;
background: darkred;
}
main {
flex: 1;
width: 80%;
margin: auto;
display: flex;
}
.content {
width: 75%;
background: yellow;
}
aside {
width: 25%;
background: fuchsia;
}
footer {
flex: 0 0 100px;
background: lightblue;
}
#media screen and (max-width: 768px) {
.banner,
main {
width: 100%;
}
main {
flex-direction: column;
order: -1;
}
.content,
aside {
flex: 1;
width: 100%;
}
aside {
flex: 0 0 150px
}
}
<div class="page">
<header>
<h2>1</h2>
</header>
<div class="banner">
<h2>2</h2>
</div>
<main>
<div class="content">
<h2>3</h2>
</div>
<aside>
<h2>4</h2>
</aside>
</main>
<footer>
<h2>5</h2>
</footer>
</div>
Codepen Demo