Problem with flexbox layout and nested scrollbar - html

Embedded scroll bars do not work within a simple flexbox container. The browser automatically displays the horizontal scroll bar.
What am I doing wrong on this simple example?
When I remove "display: flex;" on the flexContainer, the embedded scrollbar works. Of course, my entire layout is then destroyed.
I only found the following, but the solution relates to a vertical scrollbar and does not work here:
Stackoverflow nesting-flexbox-inside-flexbox-overflow-how-to-fix-this
.flexContainer {
display: flex;
}
.sidebar {
flex: 1 0 auto;
min-width: 150px;
max-width: 190px;
color: white;
background: blue;
}
.content {
flex: 1 0 auto;
background: green;
}
.scrollableElement {
display: flex;
overflow-x: scroll;
}
.textElement {
color: white;
background: grey;
}
<html>
<body>
<div class="flexContainer">
<div class="sidebar">
<div>Sidebar</div>
</div>
<div class="content">
<div class="scrollableElement">
<div class="textElement">
<div>Content11111111111111111111111111111111111111111111111111111111111111111111111</div>
<div>Content22222222222222222222222222222222222222222222222222222222222222222222222</div>
<div>Content33333333333333333333333333333333333333333333333333333333333333333333333</div>
<div>Content44444444444444444444444444444444444444444444444444444444444444444444444</div>
<div>Content55555555555555555555555555555555555555555555555555555555555555555555555</div>
<div>Content66666666666666666666666666666666666666666666666666666666666666666666666</div>
<div>Content77777777777777777777777777777777777777777777777777777777777777777777777</div>
<div>Content88888888888888888888888888888888888888888888888888888888888888888888888</div>
</div>
</div>
</div>
</div>
</body>
</html>

You need to allow .content to shrink then add min-width:0 or overflow:hidden so its size is calculated at screen inside its parent so overflow works on the children:
.content {
flex: 1 1 auto;/* updated*/
background: green;
min-width:0;/* added */
}
.flexContainer {
display: flex;
}
.sidebar {
flex: 1 0 auto;
min-width: 150px;
max-width: 190px;
color: white;
background: blue;
}
.content {
flex: 1 1 auto;
background: green;
min-width:0;
}
.scrollableElement {
display: flex;
overflow-x: scroll;
}
.textElement {
color: white;
background: grey;
}
<html>
<body>
<div class="flexContainer">
<div class="sidebar">
<div>Sidebar</div>
</div>
<div class="content">
<div class="scrollableElement">
<div class="textElement">
<div>Content11111111111111111111111111111111111111111111111111111111111111111111111</div>
<div>Content22222222222222222222222222222222222222222222222222222222222222222222222</div>
<div>Content33333333333333333333333333333333333333333333333333333333333333333333333</div>
<div>Content44444444444444444444444444444444444444444444444444444444444444444444444</div>
<div>Content55555555555555555555555555555555555555555555555555555555555555555555555</div>
<div>Content66666666666666666666666666666666666666666666666666666666666666666666666</div>
<div>Content77777777777777777777777777777777777777777777777777777777777777777777777</div>
<div>Content88888888888888888888888888888888888888888888888888888888888888888888888</div>
</div>
</div>
</div>
</div>
</body>
</html>

Your flex container has no set width, so it is taking up the entire width of the screen.
You could try setting the width to achieve the behavior you are looking for, for example:
.flexContainer {
display: flex;
width: 500px;
}
OR you could set the width of the .scrollableElement to resize based on the screen:
.scrollableElement {
overflow-x: scroll;
width: 65%;
}

Related

child container still go outside of parent 100vh

This is sort of a two in problem.
I have a body with height: 100vh similar to how my example is in the jsFiddle (except in there I put 20vh.
I have a similar structure as this, where the innerRight container can be quite large compared to the rest of the content, and only that conatiner is to obtain it's own scroll bar. I sort of got this working in my main project, but the outer container (similar to how I displayed outer in the example) still expands past the the parents height container main. Be it 100vh, or 20vh it doesn't matter it doesn't stay within with display:flex.
.main {
height: 20vh;
}
.outer {
display: flex;
overflow: hidden;
}
.innerLeft {
height: 200px;
width: 50px;
display: flex;
flex-direction: column;
flex-grow: 1;
background-color: green;
}
.innerRight {
overflow: auto;
height: 500px;
background-color: red;
width: 100%;
}
<div class="main">
<div class="header">
some random text
</div>
<div class="outer">
<div class="innerLeft">
</div>
<div class="innerRight">
</div>
</div>
</div>
Can you please check the below code? Hope it will work for you.
You have to set height:100vh; in .main and set width:calc(100% - 50px); to .innerRight.
Remove height from innerleft and innerright element.
Please refer to this link: https://jsfiddle.net/yudizsolutions/9Lsyzg64/1/
body {
margin: 0;
}
.main {
height: 100vh;
}
.outer {
display: flex;
height: calc(100vh - 19px);
overflow: hidden;
}
.innerLeft {
width: 50px;
background-color: green;
}
.innerRight {
overflow: auto;
background-color: red;
width: calc(100% - 50px);
}
<div class="main">
<div class="header">
some random text
</div>
<div class="outer">
<div class="innerLeft">
</div>
<div class="innerRight">
</div>
</div>
</div>
You need to set height to outer class.
.main {
height: 20vh;
}
.outer {
display: flex;
height: 200px;
overflow:hidden;
}
.innerLeft {
width: 50px;
display: flex;
flex-direction: column;
flex-grow: 1;
background-color: green;
}
.innerRight {
overflow: auto;
height: 500px;
background-color: red;
width:100%;
}
<div class="main">
<div class="header">
some random text
</div>
<div class="outer">
<div class="innerLeft">
</div>
<div class="innerRight">
</div>
</div>
</div>

how to set html element such that it uses up remaining viewable vertical space

I'm struggling with getting the overflow-y piece to function as described in the code. I have an element that will only take up as much vertical space as its contents and when overflowing has the parent scroll. The code in its entirety can be seen here: https://jsfiddle.net/bmts8L5x/3/ . I've had to include only a part of the code here to satisfy the code to non-code ratio for the linter here.
header {
background: yellow;
}
#first {
overflow: hidden;
}
container {
display: flex;
height: 100vh;
overflow: hidden;
}
#side {
display: flex;
flex-direction: column;
width: 200px;
overflow: scroll;
}
#side>div {
height: 200px;
}
html,
body {
margin: 0;
padding: 0;
}
main>div:first-child {
background: white;
height: 50px;
}
#big {
background: pink;
border: solid;
overflow: scroll;
display: flex;
flex: 1;
}
#big>div {
width: 1000px;
height: 100px;
/* I'd like to see #big take up the remaining space regardless of whether height here is 100px or 10000px */
}
<container>
<div id="side">
<div>
side nav does not scroll
</div>
<div>
item
</div>
<div>
item
</div>
<div>
item
</div>
<div>
item
</div>
<div>
item
</div>
</div>
<div id="first">
<header>
foo
</header>
<main>
<div>
this should remain visible after scrolling without needing position fixed
</div>
<header>
some other stuff
</header>
<div id="big">
<div>
this should take up the rest of the remaining viewable space and have any overflow be scrolled through.
<br /> X scrolls as expected but Y's overflow isn't contained to rest of viewable space.
</div>
</div>
</main>
</div>
</container>
You can nest your flexboxes even more - make your #first and main a column flexbox and give height: 100% to it:
#first, main {
display: flex;
flex-direction: column;
height: 100%;
}
See demo below:
header {
background: yellow;
}
#first {
overflow: hidden;
}
container {
display: flex;
height: 100vh;
overflow: hidden;
}
#side {
display: flex;
flex-direction: column;
width: 200px;
overflow: scroll;
}
#side>div {
height: 200px;
}
html,
body {
margin: 0;
padding: 0;
}
main>div:first-child {
background: white;
height: 50px;
}
#big {
background: pink;
border: solid;
overflow: scroll;
display: flex;
flex: 1;
}
#big>div {
width: 1000px;
height: 100px;
}
/* ADDED */
#first, main {
display: flex;
flex-direction: column;
height: 100%;
}
<container>
<div id="side">
<div>side nav does not scroll</div>
<div>item</div>
<div>item</div>
<div>item</div>
<div>item</div>
<div>item</div>
</div>
<div id="first">
<header>foo</header>
<main>
<div>
this should remain visible after scrolling without needing position fixed
</div>
<header>
some other stuff
</header>
<div id="big">
<div>
this should take up the rest of the remaining viewable space and have any overflow be scrolled through.
<br /> X scrolls as expected but Y's overflow isn't contained to rest of viewable space.
</div>
</div>
</main>
</div>
</container>

Make an element overlap others when viewport runs out of room

I have the blue square that will contain things adding up to 800px.
I want the red square to always be fully visible. That is when you narrow the viewport, the red square should overlap the blue square, and not disappear on the right like it does actually.
How can I achieve that?
.container {
display: flex;
}
div {
height: 80px;
}
.should-be-overlapped {
width: 100%;
min-width: 800px;
background: blue;
}
.always-full-width {
width: 400px;
background: red;
}
<div class="container">
<div class="should-be-overlapped"></div>
<div class="always-full-width"></div>
</div>
To accomplish that, there is mainly 2 ways.
Either add a wrapper around the blue (which I recommend).
Updated codepen
Stack snippet
.container {
position: relative;
display: flex;
}
div {
height: 80px;
}
.wrapper {
flex: 1;
overflow: hidden;
}
.should-be-overlapped {
width: 100%;
min-width: 800px;
background: blue;
}
.always-full-width {
flex: 0 0 400px;
background: red;
}
<div class="container">
<div class="wrapper">
<div class="should-be-overlapped">
</div>
</div>
<div class="always-full-width">
</div>
</div>
Or use position: absolute.
Updated codepen
.container {
display: flex;
position: relative;
overflow: hidden;
}
div {
height: 80px;
}
.should-be-overlapped {
width: 100%;
min-width: 800px;
background: blue;
}
.always-full-width {
position: absolute;
right: 0;
width: 400px;
background: red;
}
.<div class="container">
<div class="should-be-overlapped">
</div>
<div class="always-full-width">
</div>
</div>
I have the blue square that will contain things adding up to 800px.
Then you should do it with the flex: 0 1 800px, which will enable it to shrink:
.container {
display: flex;
}
div {
height: 80px;
}
.should-be-overlapped {
/*min-width: 800px;*/
flex: 0 1 800px; /* doesn't grow but shrinks, initial width set to 800px (this is also its "max-width") */
background: blue;
word-break: break-all; /* for longer unbreakable strings, just for demo */
}
.always-full-width {
/*width: 400px;*/
flex: 0 0 400px; /* since you're using flexbox, doesn't grow nor shrink, initial width set to 400px (fixed) */
background: red;
}
<div class="container">
<div class="should-be-overlapped">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
<div class="always-full-width"></div>
</div>

Chrome flexbox 100% height inside other 100% height flexbox overflows

I am trying to make a full height page using flexboxes, where the content also uses a flexbox. The page should look as follows example of what it should look like. The blue div is dynamic and could change in height and the red content should take up the remaining space of the content div. This works on both Firefox and IE, however on Chrome it overflows. Can somebody explain why it overflows on Chrome?
The HTML is as follows:
<body>
<div class="container">
<div class="navbar">Navbar</div>
<div class="content">
<div class="container">
<div class="fill"></div>
<div class="dynamic">Here is some dynamic content<br>Test</div>
</div>
</div>
</div>
</body>
And the CSS is:
body{
margin:0;
}
.container{
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.navbar{
background-color: #ccc;
flex: none;
}
.content{
background-color: #333;
flex: auto;
padding: 10px;
}
.dynamic{
background-color: #0066ff;
flex: none;
}
.fill{
flex: auto;
background-color: #ff0000;
}
Here is an updated snippet.
Use flex:1 for the container that needs to adjust the height automatically.
body {
margin: 0;
}
.container1 {
display: flex;
flex-direction: column;
width: 100%;
height: 100vh;
}
.navbar {
background-color: #ccc;
}
.content {
flex: 1;
background-color: #ff0000;
border: 10px solid #333;
border-bottom: none;
}
.dynamic {
background-color: #0066ff;
border: 10px solid #333;
border-top: none;
}
<body>
<div class="container1">
<div class="navbar">Navbar</div>
<div class="content">
</div>
<div class="dynamic">Here is some dynamic content
<br>Test</div>
</div>
</body>

Creating a cross-browser fixed height scrollable display: table-row

I am trying to create a container, of height 80% of the page height, which has a fixed height header and footer with a content pane that stretches to fit the rest of the available space.
I've tried to use display: table with the following layout:
<body>
<div class="ticket">
<div class="header">header</div>
<div class="body">
<div class="wrapper">
<div class="content">content</div>
</div>
</div>
<div class="footer">footer</div>
</div>
</body>
With these styles
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.ticket {
background: #ccc;
width: 600px;
margin: 0 auto;
height: 80%;
display: table;
}
.header {
background: blue;
height: 36px;
display: table-row;
}
.body {
background: orange;
display: table-row;
}
.wrapper {
height: 100%;
overflow-y: auto;
overflow-x: hidden;
}
.content {
height: 600px;
}
.footer {
background: green;
height: 72px;
display: table-row;
}
In Chrome this gives me a scrollable middle panel that grows with the height of the container:
Unfortunately this doesn't work in IE8 or Firefox, the '.body' div stretches to fit the '.content'.
Is there a way to do this that will work cross browser, and IE8+?
Check out http://caniuse.com/#search=flexbox and/or http://caniuse.com/#search=vh
Those are the ways to get it, but none of them works on IE 8.
You must use JS