Use 100% of remaining height - html

I'm creating an internal app so browser compatibility restrictions aren't a massive concern. I am using a div container that is using jquery ui resizable and therefore the size is unknown for any given div. I am also using a chart library (amCharts) which needs the parent div to have a height in order to render the chart.
The issue I'm facing is 100% within a div (with other elements in said div) means whilst the child div accepts 100% as verbatim and makes itself 100% of the parent div this isn't actually the intention - I want it to use the remaining space available in the div, rather than 100%.
I've tried table-row however that doesn't provide a height and therefore amcharts doesn't work well with any resizing (as it has no height/width to base itself on).
So I guess my question is, based on height, what is the best method of making a div use 100% of the remaining space, without JS and without using table/table-cell/table-row styles?
Edit: Here's a JSFiddle of the issue:
https://jsfiddle.net/2c8n1y04/
And the HTML:
<div class="a">
<div class="b"><h3>Header</h3></div>
<div class="c">
<div id="chartdiv"></div>
</div>
</div>
Styles:
html,body,.c,#chartdiv
{
height:100%
}
.a {
height:300px;
background-color: grey;
}
.b {
background-color: yellow;
}
h3 {
margin:0;
}
There is also a chart added in the JSFiddle using the amcharts library, this library is dependent on a height (otherwise it renders to 0 height). Also in the code base i'm using jquery-ui resizable ui (via gridstack) which means I am unable to define a height as the chart height simply has to stretch to the full remaining height within the div.

Any love for Does your engine support flex?
That would in my eyes be the easiest and cleanest solution.
Apply to the parent:
flex-direction: column;
display: flex;
/* or, if a prefixed version is supported, one of: */
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
and to the child to be stretched:
flex: 1;
And you should be good to go.
Demo, if your browser supports it (click on "Full page" to see the effect)
html, body {
height: 100%;
margin: 0;
}
div {
border: solid 1px #333;
padding: 5px;
}
#a {
margin: 10px;
height: calc(100% - 40px);
flex-direction: column;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
#b {
height: 100px;
background: #FFE;
}
#c {
flex: 1;
background: #EFE;
}
<div id="a">
<div id="b">Fixed</div>
<div id="c">Flexible</div>
</div>
But may I ask why you want a no-JS solution, since you're already using jQuery?

Related

Setting flex-grow: 1 causes div height to go beyond available space

I have some html like this:
.container {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
padding: 10px;
background-color: aqua;
}
.box {
width: 100%;
height: 100%;
flex-grow: 1;
background-color: cadetblue;
display: flex;
flex-direction: column;
}
.fill {
flex-grow: 1;
background-color: antiquewhite;
}
.middle {
height: fit-content;
background-color: azure;
justify-self: flex-end;
}
.bottom {
height: fit-content;
background-color: darkgray;
justify-self: flex-end;
}
<div class="container">
<h3>Title</h3>
<div>Some Stuff</div>
<div class="box">
<div class="fill">Fill</div>
<div class="middle">Middle</div>
<div class="bottom">Bottom</div>
</div>
</div>
I want the divs middle and bottom to stack at the bottom of the screen, and for the div fill to, as the name suggests, fill the remaining space without pushing the middle/bottom divs off the screen or creating a scrollbar, however it doesn't display like that:
Note that the middle and bottom divs are not visible and the scrollbar created by the fill div expanding beyond the available height.
See this StackBlitz for a demo: https://stackblitz.com/edit/angular-ivy-mwtwdg?file=src/app/hello.component.scss
I had to update a lot of CSS but feel free to take a look.
The right approach to any angular project is to have clean from the very first component (app component), and cascade it down to any other component.
Demo stackblitz
EDIT : comment explanation
"The right approach" can be explained quickly like this :
html and body should be at 100% of the page
App component should be at 100% and in display block
Any component that requires some specific layout (flex, grid), should be constrained by its parent or an absolute size, and display block.
The issue with Angular is that when you create a component, it is not set to display: block. This means the component is kind of free in the DOM flow, and this results in the kind of issues you have encountered.
When you set display: block to EVERY component (you can use angular.json to make it automatic), then you have a more deterministic approach to the CSS, where what you expect is what you get.
In your case, since the components were not display:block, they could not be constrained by height, width, or their parents.
Added to that, the fact that you wrote some probelmatic CSS (for instance, the sidenav-container being 100% of the height of its parent : what about the toolbar ?), this resulted in your issue.
As a final word, when it comes to CSS in Angular, be sure to have clean CSS from the top, and when you have any issue like you did, crawl back component by component, to find and correct the unclean ones !

Fix the size of 'html' and 'body' elements to be exactly those of the screen

I often need that html and body elements have the size of the screen. Typically, in the case when I want to have a svg element fit the whole screen.
To achieve that, I saw that it was possible to use CSS code as follow.
html,body{margin:0;padding:0;height:100%;}
The code that I personnaly use is the following one.
html {
height: 100%;
display: flex;
}
body {
flex-grow: 1;
display: flex;
flex-direction: column;
}
Both seem to work well, but I recently had the following remark.
html { height: 100%; display: flex; } is a useless declaration. html height will always be calculated to fit content. Also 100% means 100% of the parent. html has no parent... also applying flexbox to html is useless as it only has 1 child element that is visible: body.
Actually:
I put 100% of html height in order to have it fit the screen height.
I apply flexbox to html in order to be able to use flex-glow: 1 on its child, and have this child filling its parent.
Is there any better to solution than mine?
I personally use this:
html {
display: grid;
min-height: 100%;
}
This will make your body full height by default and will also respect default margin
html {
display: grid;
min-height: 100%;
background: blue;
}
body {
background: red;
}
And you can easily use height:100% on an inner element without issue:
html {
display: grid;
min-height: 100%;
background: blue;
}
body {
background: red;
}
.box {
height: 100%;
border: 5px solid green;
box-sizing: border-box;
}
<div class="box"></div>
I find that whenever working with elements that need to be the full height of the screen height: 100vh is usually a good place to start. VH = viewport height. I use it over height: 100% as depending on the layout 100% doesn't always equal the page height, so with VH you know exactly what you are getting!
With VH you can also then use a calc() in your CSS, so if you needed your body to fill the whole height of the page, but subtract the height of a header for example you could do something like this:
<header style="height: 64px">
<section style="height: calc(100vh - 64px)"

Make inner container in flex layout fit screen size

I have the following html and css code:
JSFiddle
/** CSS Framework: START **/
html {
display: flex;
}
.flexbox {
display: flex;
}
/** CSS Framework: END**/
.inner-box {
width: 100%;
overflow-x: scroll;
}
.very-big-container {
width: 4000px;
}
<div class="flexbox">
<!-- I can change everything starting from here -->
<div class="inner-box">
<div class="very-big-container">
Foobar
</div>
</div>
</div>
You see that there is a very big container which doesn't fit a normal screen size. That's why I am using inner-box for setting the max width to 100% and for enabling a horizontal scrollbar. The problem is that the scrollbar for the container inner-box does not appear. I only have a scrollbar for the whole window. I know that I can fix my problem by removing display: flex from html and flexbox, but unfortunately these properties are coming from a css framework and I cannot change anything about that. So do you have any other ideas to enable the scrollbar for inner-box?
Reason
display: flex declaration in the html element enables the flex context for all the direct children of html.
As no flex-direction and flex-wrap properties declared, their default values would get applied on html.
html {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
Solutions
Solution 1
Add flex-direction: column declaration to html element
Solution 2
Add width: 100% declaration to body element
You can use width: 100vw;
See example

display: table row does not allow scroll

I am currently designing a book website and on the right-hand side want to have a "Table of contents" which is in a fixed position and scrollable. I set the header for my website to "display: table-row" and similarly did so with the table of contents and its internal elements. (A header and a the scrollable list of chapters) As I understand it, display: table row should make a div element fill the remaining height and only the remaining height. [1] However, in this case, the content continues offscreen instead of allowing the user to scroll through it. (You can see the problem on this jsfiddle: https://jsfiddle.net/chrmon2/9wzjckvn/6/)
My css:
#container {
height: 300px;
border: 1px solid black;
}
#header {
background: blue;
display: table-row;
}
#toc h1 {
background: red;
display: table-row;
}
#toc #content {
background: yellow;
overflow-y: scroll;
display: table-row;
}
Is this not a capability of display: table-row or am I doing something wrong? Thanks
https://www.whitebyte.info/programming/css/how-to-make-a-div-take-the-remaining-height
As I understand it, the effect you want is as follows:
When there is remaining space, stretch the table of contents items;
When the space is too small, begin scrolling.
This is an ideal application of CSS Flexboxes. Flexboxes allow you to define how items stretch (or don't), how they align with each other, how they wrap etc.
In this case, we're going to use flexboxes for all the divs in this example.
.container, .toc, .content {
display: flex; /* begins flexbox layout */
flex-direction: column; /* Flexboxes can be aligned from left-to-right
or from top-to-bottom. In this case, we want
them to be top-to-bottom. */
flex-grow: 1; /* On .container, this does nothing. However, for
children of Flexboxes, this tells them to grow
if any space is still available. */
min-height: 0; /* For a more complicated reason, this is necessary
to make flexboxes scroll correctly. This needs
to be set on all the flexboxes in this example. */
}
.toc .content .item {
flex-grow: 1; /* Make items grow when there is room available */
}
.content {
overflow-y: scroll;
}
You can see the effects of this at this JSFiddle.
Just remove display: table-row from #toc #content and add this :
#content{
max-height:200px;
}
height can be as per your requirement.

Dynamic width div auto resize to fit browser width?

I have several div with unknown width(dynamic width).
How can I auto resize these div to fit browser width?
For example, I have 5 div with difference width. If the browser width only able to fill up 3 div then those 3 div will auto resize to fit the browser width and the rest will display at second row.
How can I make it using html5 and css3. I know that a new feature flexbox in css3 but i am not sure whether I can deal with it.
You can play with the calss - value acording your request.
min/max width/height
see example demo jsFiddle
.grid {
display: box;
display: -webkit-flex;
display: flex;
}
.column {
padding: 20px;
}
.fluid {
box-flex: 1;
background: #ccc;
}
.fixed {
width: 100px;
background: red;
}​