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>
Related
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>
I want to have a welcome page like this:
But instead I get this:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
background-color: #000000;
margin: 0;
height: 90%;
width: 100%;
align-items: center;
}
#container1 {
height: 100%;
vertical-align: middle;
display: table-cell;
background-color: yellow;
display: flex;
align-items: center;
}
#left {
height: 500px;
color: white;
background-color: blue;
font-size: 20px;
float: left;
width: 100%;
}
#right {
height: 500px;
color: white;
background-color: red;
font-size: 20px;
float: left;
width: 100%;
}
<main id="container1" class="container my-6">
<div class="">
<div id="left" class="col-lg-6 my-3">
</div>
</div>
<div class="">
<div id="right" class="col-lg-6 my-3">
</div>
</div>
</main>
I don't know why my container doesn't fully fit the body of the page, and my left and right don't go in the middle and stretch width to each other's end.
You have a bunch of errors in your code. I commented out the CSS you don't need:
No need for float, that's what flex is for.
display: table-cell is being overwritten by display: flex
Use flex to set the properties of your left and right divs.
Remove the containing elements around those.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
background-color: #000000;
margin: 0;
height: 90%;
width: 100%;
/* NOT NEEDED: align-items: center;*/
}
#container1 {
width: 100%;
height: 100%;
vertical-align: middle;
/* NOT NEEDED: display: table-cell; */
background-color: yellow;
display: flex;
/* This is probably unneeded. align-items, aligns elements on the cross access - which in this case would be vertically aligned in the center since flex-direction by default, is row */
align-items: center;
}
#left {
height: 500px;
color: white;
background-color: blue;
font-size: 20px;
/* NOT NEEDED float: left; */
/* NOT NEEDED width: 100%; */
flex: 1 1 50%;
}
#right {
height: 500px;
color: white;
background-color: red;
font-size: 20px;
flex: 1 1 50%;
/* NOT NEEDED float: left; */
/* NOT NEEDED width: 100%; */
}
<main id="container1" class="container my-6">
<div id="left" class="col-lg-6 my-3">
</div>
<div id="right" class="col-lg-6 my-3">
</div>
</main>
The problem comes mostly from the divs without classes, that shouldn't be there.
But you're also mixing floats, with flex and tables. Just stick with flex like in this example:
html, body{
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.container{
width: 100%;
height: 100%;
display: flex;
}
.left,
.right {
width: 50%;
height: 100%;
}
.left {
background: #215f40;
}
.right {
background: #092414;
}
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
There is a main div (#root) in which I need 4 inner divs, each one on one side fully stretched (run code snippet to see).
Right now I'm in here:
html {
height: 100%;
}
body {
height: 100%;
margin: 0;
text-align: center;
}
#root {
background-color: blue;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
height: 100%;
}
.tray {
box-sizing: border-box;
background-color: red;
border: thin solid black;
}
.tray-top {
height: 48px;
width: 100%;
}
.tray-bottom {
height: 48px;
width: 100%;
align-self: flex-end;
}
.tray-left {
width: 48px;
}
.tray-right {
width: 48px;
}
<div id="root">
<div class="tray tray-top">top</div>
<div class="tray tray-left">left</div>
<div class="tray tray-right">right</div>
<div class="tray tray-bottom">bottom</div>
</div>
Now I want left and right to stretch fully between top and bottom.
Please note that all trays have a fixed width (left, right) or fixed height (top, bottom).
I'd avoid nesting more divs into the existing ones.
Flexbox is not a must but I found it easy and future-proof compared to other possibilities.
A simple float configuration can do this without flexbox:
html,
body {
height: 100%;
margin: 0;
text-align: center;
}
#root {
background-color: blue;
height: 100%;
}
.tray {
box-sizing: border-box;
background-color: red;
border: thin solid black;
}
.tray-top,
.tray-bottom {
height: 48px;
line-height:48px;
clear: both;
}
.tray-left,
.tray-right {
width: 48px;
height: calc(100% - 96px);
float: left;
}
.tray-right {
float: right;
}
/* to align vertically the content */
.tray-left::before,
.tray-right::before {
content:"";
display:inline-block;
height:50%;
}
<div id="root">
<div class="tray tray-top">top</div>
<div class="tray tray-left">left</div>
<div class="tray tray-right">right</div>
<div class="tray tray-bottom">bottom</div>
</div>
CSS-Grid can do that:
html {
height: 100%;
}
body {
height: 100%;
margin: 0;
text-align: center;
}
#root {
background-color: blue;
display: grid;
grid-template-columns: auto 1fr auto;
grid-template-rows: auto 1fr auto;
height: 100%;
}
.tray {
box-sizing: border-box;
background-color: red;
border: thin solid black;
}
.tray-top {
height: 48px;
grid-column: 1 / -1;
}
.tray-bottom {
height: 48px;
grid-column: 1 / -1;
}
.tray-left {
width: 48px;
}
.tray-right {
width: 48px;
grid-column:3;
}
<div id="root">
<div class="tray tray-top">top</div>
<div class="tray tray-left">left</div>
<div class="tray tray-right">right</div>
<div class="tray tray-bottom">bottom</div>
</div>
For some reason, in an overflown container, the padding on the right side is not shown.
.parent {
background-color: orange;
width: 150px;
height: 50px;
overflow: auto;
padding-right: 15px;
}
.child {
background-color: blue;
width: 250px;
height: 100%;
margin: 0 10px;
}
body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
<div class="parent">
<div class="child">
</div>
</div>
I expected the orange color to show up when I scrolled to the very end (right)
Let's start without applying any overflow property. We clearly have the element outside of it's parent container (add padding of the container will remain inside):
.parent {
background-color: orange;
width: 150px;
height: 100px;
padding:15px;
}
.child {
background-color: blue;
width: 250px;
height: 100%;
}
body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
<div class="parent">
<div class="child">
</div>
</div>
Now by adding overflow:scroll or overflow:auto you will simply add the scroll to see the overflowing part and you won't have the padding as excepted:
.parent {
background-color: orange;
width: 150px;
height: 100px;
overflow:auto;
padding:15px;
}
.child {
background-color: blue;
width: 250px;
height: 100%;
}
body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
<div class="parent">
<div class="child">
</div>
</div>
Same logic with the margin right. When the element is overflowing there is no room to add margin between the inner element and the parent element.
I have checked in also Mozilla Firefox. and it's working fine.
.parent {
background-color: orange;
width: 150px;
height: 50px;
overflow-y: hidden;
overflow-x: auto;
padding-right: 15px;
}
.child {
background-color: blue;
width: 250px;
height: 100%;
margin: 0 10px;
display: inline-block;
}
body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
<div class="parent">
<div class="child">
</div>
</div>
You should use below CSS. It's working for me.
.parent {
background-color: orange;
width: 150px;
height: 50px;
padding-right: 15px;
overflow-y: hidden;
overflow-x: auto;
}
.child {
background-color: blue;
width: 250px;
height: 100%;
margin: 0 10px;
display: inline-block;
}
So I'm having some issues using <canvas>. It's taking up too much room when at 100% height and width and when it's set at only 100% height, it still causes and overflow for some reason.
Examples
With width and height at 100%, canvas takes up way too much room
.flex {
display: flex;
flex-direction: column;
height: 100vh;
}
.upper {
background-color: blue;
height: 10%;
}
.lower {
flex: 1;
background-color: orange;
}
html, body {
padding: 0;
margin: 0;
}
canvas {
height: 100%;
width: 100%;
background-color: red;
padding: 0;
margin: 0;
}
.inner {
width: 100%;
height: 100%;
background-color: yellow;
position: relative;
}
<div class="flex">
<div class="upper">
</div>
<div class="lower">
<div class='inner'>
<canvas></canvas>
</div>
</div>
</div>
Here, canvas is set at 100% height, yet it causes an overflow for some reason.
.flex {
display: flex;
flex-direction: column;
height: 100vh;
}
.upper {
background-color: blue;
height: 10%;
}
.lower {
flex: 1;
background-color: orange;
}
html, body {
padding: 0;
margin: 0;
}
canvas {
height: 100%;
background-color: red;
padding: 0;
margin: 0;
}
.inner {
width: 100%;
height: 100%;
background-color: yellow;
}
<div class="flex">
<div class="upper">
</div>
<div class="lower">
<div class='inner'>
<canvas></canvas>
</div>
</div>
</div>