Flexbox overflow scrollbar displaying on body instead of inner elements - html

The Problem:
In a full-size app layout (100% width, 100% height) using flexbox with overflow, the scrollbars do not display for overflow-y in Firefox, IE, or Edge. They do display properly in Chrome. Rather than having a vertical scrollbar in FF/IE/Edge on the element, the scrollbar is applied to the entire page.
What I've Tried:
I've tried adding, as mentioned in several other SO answers, to add min-height: 0; to the flex elements / parents. I haven't been able to get this solution to work, but perhaps I am doing something wrong.
Screenshots:
Chrome:
Firefox:
Example:
https://codepen.io/gunn4r/pen/WEoPjN
html {
height: 100%;
}
.flex-grow {
flex: 1;
}
.canvas-wrapper {
overflow: scroll;
}
.canvas {
width: 3000px;
height: 3000px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />
<body class="h-100">
<div class="h-100 container-fluid d-flex flex-column">
<div class="row bg-warning">
<div class="col-12 py-4">Top Bar</div>
</div>
<div class="row no-gutter flex-grow">
<div class="col-9 px-0 d-flex flex-column">
<div class="canvas-wrapper">
<div class="canvas bg-success">
Canvas
</div>
</div>
<div class="bg-danger py-3">
Canvas Footer
</div>
</div>
<div class="col-3 bg-primary">
<div class="sidebar-item">Sidebar</div>
</div>
</div>
<div class="row bg-warning">
<div class="col-12 py-2">Overall Footer</div>
</div>
</div>
</body>

It looks like the problem stems from this section of your code:
.canvas-wrapper {
overflow: scroll;
}
You want this element to have scrollbars. However, the element has no defined height.
From MDN:
In order for overflow to have an effect, the block-level container
must have either a set height (height or max-height) or
white-space set to nowrap.
Chrome doesn't seem to care about the height requirement. The other browsers do.
This should be enough to make it work across browsers:
.canvas-wrapper {
overflow: scroll;
flex: 1 0 1px;
}
html {
height: 100%;
}
.flex-grow {
flex: 1;
}
.canvas-wrapper {
overflow: scroll;
flex: 1 0 1px; /* NEW */
}
.canvas {
width: 3000px;
height: 3000px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<body class="h-100">
<div class="h-100 container-fluid d-flex flex-column">
<div class="row bg-warning">
<div class="col-12 py-4">Top Bar</div>
</div>
<div class="row no-gutter flex-grow">
<div class="col-9 px-0 d-flex flex-column">
<div class="canvas-wrapper">
<div class="canvas bg-success">
Canvas
</div>
</div>
<div class="bg-danger py-3">
Canvas Footer
</div>
</div>
<div class="col-3 bg-primary">
<div class="sidebar-item">Sidebar</div>
</div>
</div>
<div class="row bg-warning">
<div class="col-12 py-2">Overall Footer</div>
</div>
</div>
</body>

When using percent for height on element, all its ascendants also need a height set, and if all will have percent, one need to set it all the way up to the html/body.
When combined with Flexbox this can get really tricky to solve, as when one need to set height: 100% on all ascendants, other unwanted render issues can cause the layout to break.
Here is one solution, which work perfect cross browser, where an extra wrapper, canvas-fix, for the canvas is added, and then with position: absolute we can make this work.
Fiddle demo
Stack snippet
html {
height: 100%;
}
.flex-grow {
flex: 1;
}
.canvas-wrapper {
flex-grow: 1; /* take all remaining space */
width: 100%; /* full width */
position: relative; /* for the absolute positioned fix */
}
.canvas-fix { /* added rule */
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: scroll;
}
.canvas {
width: 3000px;
height: 3000px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />
<body class="h-100">
<div class="h-100 container-fluid d-flex flex-column">
<div class="row bg-warning">
<div class="col-12 py-4">Top Bar</div>
</div>
<div class="row no-gutter flex-grow">
<div class="col-9 px-0 d-flex flex-column">
<div class="canvas-wrapper">
<div class="canvas-fix">
<div class="canvas bg-success">
Canvas
</div>
</div>
</div>
<div class="bg-danger py-3">
Canvas Footer
</div>
</div>
<div class="col-3 bg-primary">
<div class="sidebar-item">Sidebar</div>
</div>
</div>
<div class="row bg-warning">
<div class="col-12 py-2">Overall Footer</div>
</div>
</div>
</body>

Related

Bootstrap 5 - Make div with flex-grow-1 class scrollable

I'm trying to make the indicated div below scrollable, but it always seems to extend the document size beyond screen space instead of creating a scrollbar. One solution is to set a fixed pixel height for the div, but I want to avoid this to ensure scalability between devices. Any ideas?
<div class="row no-gutters w-100 flex-grow-1">
<div class="col-8">
<div id="playarea" class="container-fluid border-top border-end h-100 px-0">
<!-- Cards go here -->
</div>
</div>
<div class="col-4">
<div class="container-fluid border rounded-top w-100 h-100 d-flex flex-column">
<div class="container my-3 d-flex mb-0">
<h5 class="flex-grow-1">Side Content</h5>
</div>
<hr class="border mt-2 mb-3">
<div class="container mb-3 d-flex">
<!-- Non-scrollable search area -->
</div>
<div class="container flex-grow-1 overflow-auto">
<!-- Scrollable content goes here -->
</div>
<div class="card mt-2 bg-light mb-3" id="info-panel">
<div class="card-body">
<!-- Non-scrollable info box -->
</div>
</div>
</div>
</div>
</div>
Many thanks in advance
Your question is a bit confusing because your .row has .flex-grow-1 which one would only add if you want .row to grow in available height of its parent, not in width. This would mean .row should always have a height and my solution can be simplified. So let me know if that's the case, because my answer assumes .row has no height.
My solution that requires no fixed height uses a container inside col-4 with absolute positioning:
#overflow-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: inherit;
}
This container will take up all available space inside col-4 and will grow or shrink with it. Now the element with overflow: scroll will work as you want.
The only drawback here is that if col-8 (or row) has no content - and thus no height - the #overflow-container will also have no height and any content inside the .overflow-auto element will not be visible. So if col-8 can be empty, a min-height on col-4s parent is needed.
The line padding: inherit is there to give the column its padding back; Bootstrap uses the selector row > * to give columns their padding.
I removed all unnecessary classes for this snippet to work for simplicity, but I added the sm breakpoint on the columns so they stack on mobile screen sizes. If you don't want this, you can simply remove the -sm part on the columns and the #media in the CSS. It's only there to show how it can be done.
.col-sm-8 {
background: lightyellow;
}
.col-sm-4 {
background: lightgreen;
}
#media (min-width: 576px) {
#overflow-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: inherit;
}
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
<div class="container-fluid">
<div class="row">
<div class="col-sm-8">
<p>This column should have enough content...</p>
<br><br><br><br><br>
<p>...So `Overflowing content` will have a height.</p>
</div>
<div class="col-sm-4 position-relative">
<div class="d-flex flex-column" id="overflow-container">
<div class="">
<h5>Aside Content</h5>
</div>
<div class="">
<p>Some content here.</p>
</div>
<div class="overflow-auto">
<p>Overflowing content.</p>
<br><br><br><br><br><br><br><br><br>
<p>Unless col-8 is long enough for me to fit.</p>
</div>
<div class="">
<p>Some content here.</p>
</div>
</div>
</div>
</div>
</div>

Boostrap grid height and placing row with height: auto

I am doing a simple page with a bootstrap grid and I am having some problems with placing the middle row occupying the full height in the middle.
These are the 3 rows: page
I want to place the row with the logo in the middle, but I am having problems with it. I placed height: 100%;, height: auto;. I even placed the container height to 100% and auto and nothing works!
I think there is a concept about bootstrap heigh that I am missing, because its the heigh that I have problems
html:
<div class="container-fluid">
<div class="row">
<div class="col-md-1 col-2">
<img id="menuIcon" (click)="toggleRightSidenav()" onmouseover="this.src='../../../assets/Images/generic/menuIcon_hover.png'" src="/assets/Images/generic/menuIcon.png" onmouseout="this.src='/assets/Images/generic/menuIcon.png'">
</div>
<div class="col-md-10 col-8">
</div>
<div class="col-md-1 col-2">
<img id="helpIcon" routerLink="/guide" onmouseover="this.src='../../../assets/Images/home/helpIconHover.png'" src="/assets/Images/home/helpIcon.png" onmouseout="this.src='/assets/Images/home/helpIcon.png'">
</div>
</div>
<div class="row row align-items-center mh-100" >
<div class= "col-md-12">
<img id="logo" src="/assets/Images/home/Logo.png">
</div>
</div>
<div class="row align-items-center justify-content-around fixed-bottom">
<div class="col-md-2 col-sm-2">
<img id="addButton" routerLink="/addPlayer" onmouseover="this.src='../../../assets/Images/generic/addIcon_hover.png'" src="../../../assets/Images/generic/addIcon.png" onmouseout="this.src='/assets/Images/generic/addIcon.png'" />
</div>
<div class="col-md-2 col-sm-2">
<p>Players Waiting: {{playerWaiting}} </p>
</div>
<div class="col-md-2 col-sm-2">
<p>Listed Players: {{playersListed}}</p>
</div>
<div class="col-md-2 col-sm-2">
<img id="searchButton" routerLink="/search" onmouseover="this.src='../../../assets/Images/generic/searchIcon_hover.png'" src="../../../assets/Images/generic/searchIcon.png" onmouseout="this.src='/assets/Images/generic/searchIcon.png'" />
</div>
</div>
</div>
css:
div{
border: yellow 1px solid;
}
#menuIcon{
width: 100%;
height: auto;
}
#helpIcon{
width: 100%;
height: auto;
}
#addButton{
width: 100%;
height: auto;
max-width: 127px;
}
#searchButton{
width: 100%;
height: auto;
max-width: 127px;
}
https://www.codeply.com/p/Xd0xi5hFNc
Couple of things.
To be able to fill several rows, you'd need a height for the container div.
Current HTML
<div class="container-fluid">
Update as
<div class="container-fluid d-flex vh-100 flex-column">
Now you can easily make your middle div fill the remaining gap by adding a fill-height class.
Current HTML
<div class="row row align-items-center mh-100" >
Update as
<div class="row row align-items-center fill-height">
Add this to your css
.fill-height {
flex: 1;
}
.fixed-bottom {
position: sticky;
}
jsFiddle

Make div fill height but not extend it (use scrollbar for overflow)

I have a specific layout that I want to achieve on my web page, namely:
The layout in the above image is built with the following HTML and bootstrap classes:
<div className="ContentWrapper d-flex mh-100 flex-row h-100">
<div className="ContentBody flex-column flex-fill">
<div className="ContentHeader p-3 w-100">
<h2>Header</h2>
</div>
<div className="ContentMain w-100">
<h2>Scrollable div, should fill height, but not more than that</h2>
</div>
</div>
<div className="Sidebar h-100">
<h2>Sidebar content</h2>
</div>
</div>
Relevant CSS:
.ContentWrapper {
background-color: red;
}
.ContentBody {
background-color: blue;
}
.ContentHeader {
background-color: yellow;
}
.ContentMain {
background-color: purple;
flex: 1;
}
.Sidebar {
background-color: green;
width: 500px;
}
However, when there is too much content in the purple part, the component starts to increase in height. I wish to prevent that and have a scrollbar in the purple component.
Furthermore, I heard that some flex properties work different in Chrome and Firefox. The idea is that I want my web page to have the same behavior in both browsers.
You can remove h-100 on ContentWrapper and add height: 100vh to it. Make your ContentBody a flexbox by adding `d-flex- class. See demo below with explanations:
.ContentWrapper {
background-color: red;
height: 100vh; /* ADDED */
}
.ContentBody {
background-color: blue;
}
.ContentHeader {
background-color: yellow;
}
.ContentMain {
background-color: purple;
flex: 1;
overflow-y: auto; /* ADDED */
}
.Sidebar {
background-color: green;
width: 500px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<div class="ContentWrapper d-flex mh-100 flex-row"> <!-- removed h-100 class -->
<div class="ContentBody d-flex flex-column flex-fill"> <!-- added d-flex class -->
<div class="ContentHeader p-3 w-100">
<h2>Header</h2>
</div>
<div class="ContentMain w-100">
<h2>Scrollable div, should fill height, but not more than that</h2>
</div>
</div>
<div class="Sidebar h-100">
<h2>Sidebar content</h2>
</div>
</div>
Just find already have an answer there...
Whatever put the codepen i just finished, which i think it is a more flexbox way.
<div class="ContentWrapper d-flex mh-100 flex-row h-100">
<div class="ContentBody flex-column flex-fill d-flex">
<div class="ContentHeader p-3 w-100">
<h2>Header</h2>
</div>
<div class="ContentMain w-100 flex-fill overflow-auto">
<h2>Scrollable div
</h2>
</div>
</div>
<div class="Sidebar h-100 flex-shrink-0">
<h2>Sidebar content</h2>
</div>
</div>
https://codepen.io/ramseyfeng/pen/drWNYQ

How to align div to bottom inside div with Bootstrap?

html, body, .sidebar-container, .sidebar-row {
height: 100%;
}
.sidebar {
background-color: #2C3544;
}
#media (min-width: 992px) {
.sidebar {
position: fixed;
top: 0;
left: 0;
bottom: 0;
z-index: 1000;
display: block;
background-color: #2C3544;
}
}
img{
margin: auto;
display: block;
}
.sidebar-image{
margin-top: 15px;
}
.sidebar-items{
margin-top: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid sidebar-container">
<div class="row sidebar-row">
<div class="col-md-2 sidebar">
<div class="container-fluid">
<div class="col-md-12 sidebar-image">
<img src="assets/logo-white.png" width="75px" height="75px"/>
</div>
</div>
<div class="row sidebar-items">
<div class="col-md-12">
<ul class="list-group">
<li class="list-group-item">Dashboard</li>
<li class="list-group-item">Projects</li>
<li class="list-group-item">Statistics</li>
</ul>
</div>
</div>
<div class="row align-bottom">
hafldjalfjsdlfsjdlfsjlfs
</div>
</div>
<div class="col-md-10 offset-md-2 content">
Main Content
</div>
</div>
</div>
I wrote this HTML/CSS code trying to align a div to the bottom inside another div:
I want to align this last div in the col-md-2 to the bottom of the sidebar-container which height is 100%. I tried adding the bootstrap class align-bottom but somehow this doesn't work. Could anyone help me out?
Suppose you have 2 divs. Div A(Outer) and Div B(Inner). To achieve your task just place Div B code in Div A code and in Div B css class add this
position : absolute
bottom : 0
You can also just use bootstrap flexbox to do this.
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<div class="d-flex align-items-start flex-column bg-success" style="height: 200px;">
<div class="mb-auto p-2">Flex item-1</div>
<div class="p-2">Flex item-2</div>
<div class="p-2">Flex item-3</div>
</div>
<div class="d-flex align-items-end flex-column bg-info" style="height: 200px;">
<div class="p-2">Flex item-a</div>
<div class="p-2">Flex item-b</div>
<div class="mt-auto p-2">Flex item-c</div>
</div>
align items to the left or right make sure that you include the entire d-flex align-items-end flex-column on the parent element and choose start or end depending if you want it to be aligned left or right.
align item to the bottom Then, use mt-auto on the div that you want to stick to the bottom of the parent.
When using Bootstrap grid system, my go-to solution is like this:
add d-flex to each col-*
add d-flex flex-column to each card-body
add mt-auto mx-auto to the last element (or last div of elements) I want to stick to the end
This prevents any further styling mess-up in my opinion.
Relevant Documentation:
Flex Alignment in Bootstrap 5.0: https://getbootstrap.com/docs/5.0/utilities/flex/#align-items
Vertical Alignment in Bootstrap 5.0: https://getbootstrap.com/docs/5.0/utilities/vertical-align/
Relevant Code:
What worked for me to align a div (of text) at the bottom of a row/container
<div class="d-flex align-content-end flex-wrap mb-2">
<span class="display-4 fw-bold text-black text-start mt-0 mb-0">Active Mural Projects</span>
</div>

Removing padding on columns makes horizontal scrollbar

I wanted to remove the padding from the bootstrap grid column classes.
So I did
.col-x {
padding: 0;
}
But this is kind of breaking the whole layout because a horizontal scrollbar appears.
I've created a pen for this so you can see it.
What is causing the horizontal scrollbar and how to fix it?
The .row has minus margins on them. Also the .content-fluid has padding applied to them. So you just need to add this to your CSS:
.row {
margin:0;
}
.container-fluid {
padding:0;
}
You have .row elements nested in your columns. .row has a negative margin and always needs to be wrapped in a .container, which has padding that the negative margin offsets. The padding on your columns were doing that. I would just wrap all of your rows in .container-fluid
Rows are placed within a fixed or full-width Container (.container or .container-fluid, respectively) for proper alignment.
/* removing padding on columns makes horizontal scrollbar */
.column {
padding: 0;
}
.column {
min-height: 100vh;
border-right: 1px solid #ccc;
}
.column-header {
border-bottom: 1px solid #ddd;
}
.column.sidebar {
position: fixed;
top: 0; left: 0;
border-right: 1px solid #ccc;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid">
<div class="row">
<div class="col-2 column sidebar">
fixed side
</div>
<div class="col-6 offset-2 column content">
<div class="column-header mb-5">
<div class="container-fluid">
<div class="row">
<div class="col-8 pt-4 pb-4 pl-5 pr-5">
Title
</div>
<div class="col-4 pt-4 pb-4 pl-5 pr-5 text-right">
Right
</div>
</div>
</div>
</div>
</div>
<div class="col-4 column content">
<div class="column-header mb-5">
<div class="container-fluid">
<div class="row">
<div class="col-8 pt-4 pb-4 pl-5 pr-5">
Title
</div>
<div class="col-4 pt-4 pb-4 pl-5 pr-5 text-right">
Right
</div>
</div>
</div>
</div>
</div>
</div>
</div>