vertical scrollbar not showing in flexbox children - html

I want the top panel to have no scrollbars and the two bottom panels to have both horizontal and vertical scrollbars.
The horizontal scrollbars for the bottom panels do not work.
If I delete the top div, the scrollbars behave just fine.
<style>
* {
font-size: 200px;
}
html,body {
height: 100%;
width: 100%;
margin: 0;
overflow: hidden;
}
.splitter {
display: flex;
overflow: hidden;
height: 100%;
width: 100%;
}
.left {
background-color: bisque;
overflow: scroll;
}
.right {
background-color: rgb(67, 228, 62);
overflow: scroll;
}
.top {
background-color: red;
}
</style>
<div class="top">
top
</div>
<div class="splitter">
<div class="left">
this is panel 1
</div>
<div class="right">
this is panel 2
</div>
</div>

This is how I managed to get it working, you might be able to tweak it to your liking. I think this type of layout in isolation is terrible as it's not responsive to the content/device.
* {
font-size: 200px;
box-sizing: border-box;
}
html,
body {
max-height: 100%;
}
body {
display: flex;
flex-flow: column nowrap;
margin: 0;
}
.splitter {
max-height: 90vh;
flex: 50% 1 1;
display: flex;
overflow: hidden;
}
.left,
.right {
overflow: scroll;
}
.left {
background-color: bisque;
}
.right {
background-color: rgb(67, 228, 62);
}
.top {
background-color: red;
flex: 50% 1 1;
}
<div class="top">
top
</div>
<div class="splitter">
<div class="left">
this is panel 1
</div>
<div class="right">
this is panel 2
</div>
</div>

Related

Why overflow-y may affect horizontal layout in flex?

Consider the following flex layout:
body {
margin: 0;
}
.container {
background: red;
color: white;
height: 100vh;
display: flex;
}
.left {
flex-grow: 1;
height: 100%;
padding: 1em;
}
.main-content {
background: blue;
height: 130%;
}
.right {
height: 100%;
}
.side-content-upper {
padding: 1em;
height: 50%;
}
.side-content-lower {
padding: 1em;
height: 60%;
background: black;
}
<div class="container">
<div class="left">
<div class="main-content">some some some some some some some some some some some some some some some some some some some some some</div>
</div>
<div class="right">
<div class="side-content-upper">more</div>
<div class="side-content-lower">more</div>
</div>
</div>
Since heights of .main-content and of .side-content-upper plus that of .side-content-lower are greater than 100%, we get vertical overflow. Now let's make the first column fit the screen height and scroll separately by adding box-sizing: border-box; overflow-y: scroll; (to make this more compact, I align unchanged CSS into single lines):
body { margin: 0; }
.container { background: red; color: white; height: 100vh; display: flex; }
.left {
flex-grow: 1;
height: 100%;
padding: 1em;
box-sizing: border-box;
overflow-y: scroll;
}
.main-content { background: blue; height: 130%; }
.right {
height: 100%;
}
.side-content-upper { padding: 1em; height: 50%; }
.side-content-lower { padding: 1em; height: 60%; background: black; }
<div class="container">
<div class="left">
<div class="main-content">some some some some some some some some some some some some some some some some some some some some some</div>
</div>
<div class="right">
<div class="side-content-upper">more</div>
<div class="side-content-lower">more</div>
</div>
</div>
Works fine, doesn't it? Let's now apply the same style to the .right container:
body { margin: 0; }
.container { background: red; color: white; height: 100vh; display: flex; }
.left {
flex-grow: 1;
height: 100%;
padding: 1em;
box-sizing: border-box;
overflow-y: scroll;
}
.main-content { background: blue; height: 130%; }
.right {
height: 100%;
box-sizing: border-box;
overflow-y: scroll;
}
.side-content-upper { padding: 1em; height: 50%; }
.side-content-lower { padding: 1em; height: 60%; background: black; }
<div class="container">
<div class="left">
<div class="main-content">some some some some some some some some some some some some some some some some some some some some some</div>
</div>
<div class="right">
<div class="side-content-upper">more</div>
<div class="side-content-lower">more</div>
</div>
</div>
If your screen resolution is not too high, you'll see what I'm not expecting: the right column not only fits height and gets vertical scroll, but also shrinks and gets horizontal scroll. Why is that? It doesn't seem just the width of the vertical scrollbar: switch overflow-y of .right from scroll to hidden and you again will get .right deformed. I'm puzzled how to reason about this. Just in case, here's what I see with hidden:
Here are two 'fixes' for what it's worth - I know you're looking for an explanation more than a solution but hopefully this will help explain by example. I'm not confident I can detail the intricacies of what is happening here but it is basically do with the way scroll bars interact with with the box model, and how flex handles dimensions. If anyone more knowledgeable can shed some light please chime in.
Give the right div it's own flex property:
body { margin: 0; }
.container { background: red; color: white; height: 100vh; display: flex; }
.left {
flex: 5;
height: 100%;
padding: 1em;
box-sizing: border-box;
overflow-y: scroll;
}
.main-content { background: blue; height: 130%; }
.right {
flex: 1;
height: 100%;
box-sizing: border-box;
overflow-y: scroll;
}
.side-content-upper { padding: 1em; height: 50%; }
.side-content-lower { padding: 1em; height: 60%; background: black; }
<div class="container">
<div class="left">
<div class="main-content">some some some some some some some some some some some some some some some some some some some some some</div>
</div>
<div class="right">
<div class="side-content-upper">more</div>
<div class="side-content-lower">more</div>
</div>
</div>
Give the .side-content-upper and .side-content-lower a box-sizing: border-box property.
body { margin: 0; }
.container {
background: red;
color: white;
height: 100vh;
display: flex;
}
.left {
flex: 1;
height: 100%;
padding: 1em;
box-sizing: border-box;
overflow-y: scroll;
}
.main-content { background: blue; height: 130%; }
.right {
height: 100%;
box-sizing: border-box;
overflow-y: scroll;
}
.side-content-upper { padding: 1em; box-sizing: border-box; height: 50%; width: 100%; }
.side-content-lower { padding: 1em; box-sizing: border-box; height: 60%; background: black; width: 100%;}
<div class="container">
<div class="left">
<div class="main-content">some some some some some some some some some some some some some some some some some some some some some</div>
</div>
<div class="right">
<div class="side-content-upper">more</div>
<div class="side-content-lower">more</div>
</div>
</div>
One final note: when you give overflow to both the left and right divs, the container loses its implicit overflow: auto which was spacing your elements for you. This was causing the shrink issue - if you add overflow-y: scroll back on the container in your last demo the elements will regain their original proportions.
can use java script to help you by available screen height
add jquery.js in first
<script type="text/javascript">
$(document).ready(function(){
var y = screen.availHeight;
$(".container").css('height',y +'px');
$(".left").css('height',y +'px');
$(".right").css('height',y +'px');
$(".main-content").css('height',(y * 1.3) +'px');
$(".side-content-upper").css('height',(y * .5)
+'px');
$(".side-content-lower").css('height',(y * .6)
+'px');
});
</script>
<style type="text/css">
body { margin: 0; }
.container{
background: red;
color: white;
display: flex;
flex-wrap:wrap;
}
.left {
flex-grow: 1;
padding: 1em;
box-sizing: border-box;
overflow-y:scroll;
}
.main-content{ background: blue;}
.right{box-sizing: border-box;overflow-y: scroll;}
.side-content-upper { padding: 1em; }
.side-content-lower { padding: 1em; background:
black; }
</style>

Prevent element from overflowing container

I have the following structure, where the number of names (.name) in .list is dynamic. What i would like to achieve is when content (depending on n of .names) is longer than .parent's fixed height, both .children fit inside the .parent (inherit height). Lack of space would be solved with .list getting a scrollbar (overflow:auto).
Height inheritance works well with single child, but I am having huge problems when there are two or more.
JSFIDDLE HERE
HTML
<div id="grandparent">
<div id="parent">
<div id="list" class="children">
<div class="name">john</div>
<div class="name">mike</div>
<div class="name">jack</div>
<div class="name">terry</div>
</div>
<div id="footer" class="children">
<div>footer</div>
</div>
</div>
</div>
CSS
body, html {
margin: 0;
width: 100%;
height: 100%;
}
div {
box-sizing: border-box;
}
#grandparent {
background-color:yellow;
display:flex;
align-items:center;
width:100%;
height: 100%;
flex: 1;
}
.children, .children div {
padding: 5px;
}
.children {
max-height: inherit;
}
.children div {
width: 100%;
max-height: inherit;
}
#list {
overflow: auto;
padding-bottom:0;
}
#footer {
padding-top:0;
}
.name {
background-color: green;
}
#footer div {
background-color: pink;
}
#parent {
background-color: blue;
margin: 0 auto;
max-height: 100px;
}
P.S. sorry for the code mess, i was just testing out different options.
Add this to your code:
#parent {
display: flex;
flex-direction: column;
}
body,
html {
margin: 0;
width: 100%;
height: 100%;
}
div {
box-sizing: border-box;
}
#grandparent {
background-color: yellow;
display: flex;
align-items: center;
width: 100%;
height: 100%;
flex: 1;
}
.children,
.children div {
padding: 5px;
}
.children {
max-height: inherit;
}
.children div {
width: 100%;
max-height: inherit;
}
#list {
overflow: auto;
padding-bottom: 0;
}
#footer {
padding-top: 0;
}
.name {
background-color: green;
}
#footer div {
background-color: pink;
}
#parent {
background-color: blue;
margin: 0 auto;
max-height: 100px;
/* new */
display: flex;
flex-direction: column;
}
<div id="grandparent">
<div id="parent">
<div id="list" class="children">
<div class="name">john</div>
<div class="name">mike</div>
<div class="name">jack</div>
<div class="name">terry</div>
</div>
<div id="footer" class="children">
<div>footer</div>
</div>
</div>
</div>
jsFiddle demo
Because flex items are set to flex-shrink: 1 by default, they will reduce their size in order to not overflow the container.

2nd Column fill remaining screen height not working

I have a navbar with a fixed height, underneath a control div with also a fixed height and below that I have another div calendar. calendar is scrollable. I want the calendar height to have the remaining screen height below control and the bottom of the screen. This way the window is not scrollable, only the calendar is scrollable. However setting height: 100% does not work and flex: 1 neither.
This is what I have when I set the height of calendar to a fixed height but as I explained I want the height to be the rest of the screen size.
Any Idea?
.navbar {
height: 50px;
background-color: indianred;
}
.window {
display: flex;
flex-direction: column;
flex: 1;
}
.control {
height: 100px;
background: khaki;
}
.calendar {
height: 200px;
width: 100%;
bottom: 0;
left: 0;
}
.wrapper {
position: relative;
background-color: lightgray;
width: 100%;
height: 100%;
overflow: scroll;
}
.main {
width: 1500px;
height: 1500px;
background-color: rosybrown;
display: flex;
flex-direction: column;
}
<nav class="navbar"></nav>
<div class="window">
<div class="control">
</div>
<div class="calendar">
<div class="wrapper">
<div class="main">
</div>
</div>
</div>
</div>
Run this Code below:
I used height: calc() method full height of the screen minus 150px for nav and controls.
.navbar {
height: 50px;
background-color: indianred;
}
.window {
display: flex;
flex-direction: column;
flex: 1;
}
.control {
height: 100px;
background: khaki;
}
.calendar {
height: calc(100vh - 150px);
width: 100%;
bottom: 0;
left: 0;
}
.wrapper {
position: relative;
background-color: lightgray;
width: 100%;
height: 100%;
overflow: scroll;
}
.main {
width: 1500px;
height: 1500px;
background-color: rosybrown;
display: flex;
flex-direction: column;
}
<nav class="navbar"></nav>
<div class="window">
<div class="control">
</div>
<div class="calendar">
<div class="wrapper">
<div class="main">
</div>
</div>
</div>
</div>

How to make inner div of Flexbox height of parent

I am using the flexbox to lay out a web app. It works, except for the main content area. The "router-view" is the expected full height. But the div inside of this is NOT full height of the router-view?
How do I make the div with id of "make-full-height" full height?
I have tried setting the height to 100%, but this has no effect.
html
<div class="full-screen flex-container-column">
<div class="header no-flex">
Fixed Header
</div>
<!--The router-view IS full height-->
<router-view class="flexible">
<div id="make-full-height">
How do I make this div full height?
</div>
</router-view>
<div class="footer no-flex">
Fixed Footer
</div>
</div>
css
.full-screen {
height: 100vh;
}
.flex-container-column {
display: flex;
flex-direction: column;
}
.no-flex {
flex: 0 0 auto;
overflow: auto;
}
.footer {
height: 30px;
background: #555;
color: white;
}
.header{
height: 50px;
background: #555;
color: white;
}
.flex-container {
flex: 1 1 auto;
display: flex;
overflow: hidden;
}
.left, .right {
width: 200px;
background: #eee;
}
.flexible {
flex: 1 1 auto;
}
Set the <router-view to have display: flex, and set flex:1 for the #make-full-height. This way #make-full-height will fill it's container since there are no other children.
.full-screen {
height: 100vh;
}
.flex-container-column {
display: flex;
flex-direction: column;
}
.no-flex {
flex: 0 0 auto;
overflow: auto;
}
.footer {
height: 30px;
background: #555;
color: white;
}
.header{
height: 50px;
background: #555;
color: white;
}
.flex-container {
flex: 1 1 auto;
display: flex;
overflow: hidden;
}
.left, .right {
width: 200px;
background: #eee;
}
.flexible {
flex: 1 1 auto;
background-color: #88F;
display: flex;
}
#make-full-height {
flex : 1;
background-color: #8F8;
}
<div class="full-screen flex-container-column">
<div class="header no-flex">
Fixed Header
</div>
<!--The router-view IS full height-->
<router-view class="flexible">
<div id="make-full-height">
How do I make this div full height?
</div>
</router-view>
<div class="footer no-flex">
Fixed Footer
</div>
</div>

height: 100% to use the remaining height?

The red is the header.
Then I have 5 rows, where I want to let use each 20% of the remaining space.
But instead it takes 20% of the window space. How can this be fixed?
html:
<div id="container">
<div id="header"></div>
<div id="items">
<div class="item" id="item1"></div>
<div class="item" id="item2"></div>
<div class="item" id="item3"></div>
<div class="item" id="item4"></div>
<div class="item" id="item5"></div>
</div>
</div>
css:
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
}
#container {
position: relative;
width: 100%;
height: 100%;
}
#header {
position: relative;
width: 100%;
height: 10%;
background: red;
}
#items {
position: relative;
width: 100%;
height: 100%;
}
.item {
height: 20%;
width: 100%;
}
#item1 {
background: green;
}
#item2 {
background: blue;
}
#item3 {
background: orange;
}
#item4 {
background: purple;
}
#item5 {
background: brown;
}
http://jsfiddle.net/clankill3r/dabrm8js/
#items {
position: relative;
width: 100%;
height: 90%;
}
10% is taken by header, so you have 90% of height for items (and not all 100%)...
Set the height of your items div to 90%.
Next to the header (10%) they will fill the screen. Then the .item divs will each take up to 20% of their parent (#items).
So try
#items {
position: relative;
width: 100%;
height: 90%;
}
You can do this with CSS tables.
1) Set display:table on the container and give it a background color (this will be the color of the header)
2) Set display:table-row on the header and items
FIDDLE
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
}
#container {
display: table;
width: 100%;
height: 100%;
background: red;
}
#header {
display: table-row;
width: 100%;
height: 40%;
}
#items {
display: table-row;
height: 100%;
}
.item {
height: 20%;
width: 100%;
}
#item1 {
background: green;
}
#item2 {
background: blue;
}
#item3 {
background: orange;
}
#item4 {
background: purple;
}
#item5 {
background: brown;
}
<div id="container">
<div id="header"></div>
<div id="items">
<div class="item" id="item1"></div>
<div class="item" id="item2"></div>
<div class="item" id="item3"></div>
<div class="item" id="item4"></div>
<div class="item" id="item5"></div>
</div>
</div>
NB: If CSS3 is an option this can also be done with flexbox.
I'd use flex boxes for this:
#container {
display: flex;
flex-direction: column;
height: 100%;
}
#header {
flex: 0 0 auto; /* fixed height */
min-height: 10%; /* you don't need this? */
}
#items {
flex: 1 0 auto; /* take the remaining height (grow) */
display: flex;
flex-direction: column;
}
.item {
flex: 1 1 auto; /* distribute height equally, 20% height for 5 rows, 25% for 4 etc. */
}
(test)
For older browsers support you need to add prefixed version of the properties and the older properties (like box-orient)
Tables may do the job too, if you can live with their limitations with padding, margins and positioning
Height of items need to be 90% as 10% is already used by header part.