Canvas pushes other flexbox items outside the container - html

I am creating a drawing app for mobile and web. The UI structure is as in the attached code sample. I want the canvas to take maximum possible space without pushing other content outside the parent flexbox.
Currently, as I resize the window from portrait to landscape mode, the canvas grows and pushes other boxes out of the view.
Prefer codepen to check the output, as the output window can be easily resized there.
body {
margin: 0;
padding: 0;
}
.root {
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
overflow: hidden;
}
.header {
flex: 0 0 60px;
background: #ff9;
}
.box1 {
flex: 0 0 20px;
background: #f9f;
}
canvas {
background: black;
max-width: 100%;
max-height: 100%;
}
.canvas-box {
flex: 1 1 400px;
background: #f99;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.box3 {
flex: 0 0 150px;
background: #9ff;
}
.box4 {
flex: 0 0 20px;
background: #9f9;
}
.in-box1 {
flex: 0 0 40px;
height: 100%;
background: #ff0;
}
.in-box2 {
flex: 1 1;
background: #fff;
}
.in-box3 {
flex: 0 0 40px;
height: 100%;
background: #0ff;
}
<div class="root">
<div class="header"></div>
<div class="box1"></div>
<div class="canvas-box">
<div class="in-box1"></div>
<div class="in-box2">
<canvas width="1000" height="1000" />
</div>
<div class="in-box3"></div>
</div>
<div class="box3"></div>
<div class="box4"></div>
</div>
Codepen link: https://codepen.io/80avin/pen/oNxWyje

Related

flexbox - center items for 1/3 and 2/3 proportion

I need to center item (one) in 1/3 row space and center another item (two) in the rest of the row space (2/3).
https://jsfiddle.net/gpe9a5qb/1/
How to center items to the specific space they fit so they will NOT center depends on their size but depend on the size of the space they are signed (1/3 and 2/3)?
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
.container {
background: red;
width: 250px;
height: 100px;
}
.box {
display: flex;
align-items: center;
justify-content: space-around;
}
.one {
background: green;
flex: 1 1 auto;
}
.two {
background: blue;
flex: 2 1 auto;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
.one should be center inside 1/3 and .two must be center inside 2/3 space.
If i get this correctly, you are speaking about center horizontally.
the css will look like this
body
{border:1px dotted yellow;
margin:0;
padding:0;
width:100%;
height:100%;
background:brown;}
.container{
background:red;
width:250px;
height:100px;}
.box
{display:flex;
}
.box > div{
display:flex;
justify-content:center;
}
.one
{
background:green;
flex-basis:33.33%;
}
.two
{background:blue;
flex-basis:66.66%;}
Hope this helps.
What i did here, is that i put flex on the inside divs, and center their content(not the parent container, which you cant center , because they take up the space).
You were almost there. Just one modification needed:
Make each flex item a flex container with justify-content: center.
That's it.
.container {
background: red;
width: 250px;
height: 100px;
}
.box {
display: flex;
align-items: center;
/* justify-content: space-around */ /* remove; doing nothing */
}
.one {
background: green;
flex: 1 1 auto;
/* NEW */
display: flex;
justify-content: center;
}
.two {
background: blue;
flex: 2 1 auto;
/* NEW */
display: flex;
justify-content: center;
}
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
If I understand you correctly, you want both your .one and .two elements to be vertically centered inside of .box, whilst still taking up one-third and two-thirds of the space respectively.
In order to achieve this, you simply need to ensure that .box takes up the full height of .container.
You can achieve this by either setting display: flex on .container along with flex: 1 on .box:
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
.container {
background: red;
width: 250px;
height: 100px;
display: flex;
}
.box {
display: flex;
align-items: center;
justify-content: space-around;
flex: 1;
}
.one {
background: green;
flex: 1 1 auto;
}
.two {
background: blue;
flex: 2 1 auto;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
Or simply by setting height: 100% on .box:
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
.container {
background: red;
width: 250px;
height: 100px;
}
.box {
display: flex;
align-items: center;
justify-content: space-around;
height: 100%;
}
.one {
background: green;
flex: 1 1 auto;
}
.two {
background: blue;
flex: 2 1 auto;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</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>

Flexbox: shrink image to fit

I am trying to design a page with the following properties that will be used as digital signage:
Page height is viewport height (100vh) so that scrolling is impossible
Page is arranged into full-width rows
All rows but the last are static (have pre-defined content)
Last row (which will contain an image slideshow) should fill the remaining space in the viewport.
Here is what I have so far:
body {
margin: 0;
}
div#container {
display: flex;
flex-direction: column;
height: 100vh;
}
div.red {
height: 100px;
background-color: red;
flex: 0 0 auto;
}
div.blue {
height: 150px;
background-color: blue;
flex: 0 0 auto;
}
div.green {
background-color: green;
flex: 0 1 auto;
}
img {
max-height: 100%;
}
<div id="container">
<div class="red"></div>
<div class="blue"></div>
<div class="green">
<img src="http://lorempixel.com/200/300/">
</div>
</div>
https://jsfiddle.net/62qqnx3m/6/
Clearly this is not working because flex is not shrinking the image div to the right size.
I can remove the flex: 0 0 auto from the first two divs, but then they shrink instead.
How can I force the green div/image to take up exactly what space remains, no more, no less?
So if a taller image was supplied, it would shrink even more to fit.
And if an image is smaller than the available space, it should simply display, with the background div still filling the available space.
It seems like max-height:100% would be great for this, but that also does not work.
Furthermore, I have seen examples of how to do this horizontally (which I also need, but am having less trouble with), but I can't figure out how to translate that into vertical scaling.
You can set the position of the green block to relative and the position of the image to absolute.
Also make sure the height of the green block is set to 100% (to take the rest of the height of the page).
This should fix the problem:
body {
margin: 0;
}
div#container {
display: flex;
flex-direction: column;
height: 100vh;
}
div.red {
height: 100px;
background-color: red;
flex: 0 0 auto;
}
div.blue {
height: 150px;
background-color: blue;
flex: 0 0 auto;
}
div.green {
background-color: green;
flex: 0 1 auto;
position: relative;
height: 100%;
}
img
{
max-height: 100%;
position: absolute;
}
<body>
<div id="container">
<div class="red"></div>
<div class="blue"></div>
<div class="green"><img src="http://lorempixel.com/200/300/"></div>
</div>
</body>
So here's what we know:
The page height is 100vh
The first row is static (height: 100px)
The second row is static (height: 150px)
The third row, which contains images, should fill the remaining height
I think the solution lies in basic math:
100vh - 100px - 150px = height of third row
Instead of this in your code:
div.green {
background-color: green;
flex: 0 1 auto;
}
img {
max-height: 100%;
}
Try this:
div.green {
background-color: green;
flex: 1 1 auto;
}
img {
height: calc(100vh - 250px);
}
body {
margin: 0;
}
div#container {
display: flex;
flex-direction: column;
height: 100vh;
}
div.red {
height: 100px;
background-color: red;
flex: 0 0 auto;
}
div.blue {
height: 150px;
background-color: blue;
flex: 0 0 auto;
}
/*
div.green {
background-color: green;
flex: 0 1 auto;
}
img
{
max-height: 100%;
}
*/
div.green {
background-color: green;
flex: 1 1 auto;
}
img {
height: calc(100vh - 250px);
}
<div id="container">
<div class="red"></div>
<div class="blue"></div>
<div class="green">
<img src="http://lorempixel.com/200/300/">
</div>
</div>
revised fiddle
I just change the img class and add to class .green min-height: 100%; Additionally the image is responsive now with that code.
body {
margin: 0;
}
div#container {
display: flex;
flex-direction: column;
height: 100vh;
}
div.red {
height: 100px;
background-color: red;
flex: 0 0 auto;
}
div.blue {
height: 150px;
background-color: blue;
flex: 0 0 auto;
}
div.green {
background-color: green;
flex: 0 1 auto;
min-height: 100%;
}
.green img {
max-width: 100%;
display: block;
margin: 0 auto;
height: auto;
}
<body>
<div id="container">
<div class="red"></div>
<div class="blue"></div>
<div class="green"><img src="http://lorempixel.com/200/300/"></div>
</div>
</body>
Try this fiddle: https://jsfiddle.net/ez4pf8wp/
Added this to the img class:
img {
max-height: 100%;
height: 100%;
display: block;
margin: 0;
}

Wrap element to new line/row using flexbox

I have trouble forcing an item into the next row in a flexbox layout.
How can I do something like the following image?
This is what I got so far:
#wrap {
display: flex;
width: 86vw;
height: auto;
box-sizing: border-box;
margin: 0 auto;
}
.item1,
.item2 {
width: 50%;
height: 24.5vw;
background: #4add69;
}
.item1 {
margin-right: 10px;
}
.item2 {
margin-left: 10px;
}
.item3 {
width: 60%;
height: 40vw;
background: #d56c6c;
}
<div id="wrap">
<div class="item1"></div>
<div class="item2"></div>
<div class="item3"></div>
</div>
Your code is fine but missing two things.
Use flex-wrap: wrap to
create a new row. Modify the width of the first two items to be
present in a single row.
For the last two items, you need to nest it inside a container and
then wrap them again.
Manipulate the dimension(width, height) and margin values to achieve the perfect/suitable layout.
JSfiddle Demo
* {
margin: 0;
padding: 0;
}
body {
background: #232323;
padding: 10px;
}
#wrap {
display: flex;
width: 86vw;
height: auto;
box-sizing: border-box;
margin: 0 auto;
flex-wrap: wrap;
background: #232323;
/* Added */
}
.item1,
.item2 {
width: 48%;
/* Modified */
height: 24.5vw;
background: #4add69;
margin-bottom: 10px;
}
.item1 {
margin-right: 10px;
}
.item2 {
margin-left: 10px;
}
.item3 {
width: 55%;
height: 40vw;
background: #d56c6c;
margin-right: 10px;
}
.nested-items {
display: flex;
width: 42%;
flex-wrap: wrap;
align-content: space-between;
}
.item4,
.item5 {
background: lightblue;
width: 100%;
height: 49%;
}
<div id="wrap">
<div class="item1"></div>
<div class="item2"></div>
<div class="item3"></div>
<div class="nested-items">
<div class="item4"></div>
<div class="item5"></div>
</div>
</div>
Essentially you need an extra wrapping div for the two 'small' elements like so:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrap {
width: 75%;
margin: 1em auto;
border: 1px solid green;
padding: .25em;
display: flex;
flex-wrap: wrap;
}
.wrap div {
border: 1px solid grey;
margin-bottom: 1px;
}
.box {
height: 80px;
background: lightblue;
flex: 0 0 50%;
}
.tall {
flex: 0 0 65%;
height: 160px;
}
.col {
flex: 0 0 35%;
display: flex;
flex-wrap: wrap;
}
.mini {
flex: 0 0 100%;
height: 80px;
background: pink;
}
<div class="wrap">
<div class="box"></div>
<div class="box"></div>
<div class="box tall"></div>
<div class="box col">
<div class="mini"></div>
<div class="mini"></div>
</div>
</div>
I've used a single overall element here with wrapping but the image suggests that this would be much simpler with actual rows and the extra wrapper mentioned before.
Codepen Demo of 2nd option with rows.

Make HTML5 details tag to take maximum available height

I have an HTML page with header/content/footer that uses flexbox model and contains <details> tag.
I need to make details content use maximum available height, meaning that when in opened state its content should occupy all space in its container (except for summary of course).
Here is my HTML/CSS code (http://jsfiddle.net/rtojycvk/2/):
HTML:
<div class="wrapper">
<div class="header">Header</div>
<div class="main">
Some text before details
<details class="details" open>
<summary>Details summary</summary>
<div class="content">Details content</div>
</details>
</div>
<div class="footer">Footer</div>
</div>
CSS:
html, body {
height: 100%;
margin: 0; padding: 0;
}
.wrapper {
display: flex;
flex-direction: column;
width: 100%;
min-height: 100%;
}
.header {
height: 50px;
background-color: yellow;
flex: 0 0 auto;
}
.main {
background-color: cyan;
flex: 1;
display: flex;
flex-direction: column;
}
.footer {
height: 50px;
background-color: green;
flex: 0 0 auto;
}
.content {
background-color: blue;
color: white;
flex: 1;
}
.details {
background-color: red;
flex: 1;
display: flex;
flex-direction: column;
}
As you can see, the details tag itself takes all the available space, but not its content.
P.S. I need this to work only in Chrome.
http://jsfiddle.net/rtojycvk/16/
use position absolute on content, position relative on details, and calc() css (to offset the summary height)
.content {
background-color: lightgray;
color: black;
flex: 1;
display:flex;
position:absolute;
height: calc(100% - 18px);
width: 100%;
}
.details {
background-color: gray;
flex: 1;
display: flex;
flex-direction: column;
position:relative;
}
hope this helps! (I changed the colors cause they were a bit bright for me :p)
Absolute positioned .content and details relative.
fiddle
html, body {
height: 100%;
margin: 0; padding: 0;
}
.wrapper {
display: flex;
flex-direction: column;
width: 100%;
min-height: 100%;
}
.header {
height: 50px;
background-color: yellow;
flex: 0 0 auto;
}
.main {
background-color: cyan;
flex: 1;
display: flex;
flex-direction: column;
}
.footer {
height: 50px;
background-color: green;
flex: 0 0 auto;
}
.content {
background-color: blue;
color: white;
flex: 1;
position: absolute;
top: 3%;
bottom: 0;
height: 97%;
width: 100%;
}
details {
position: relative;
}
summary{
height: 3%;
}
.details {
background-color: red;
flex: 1;
display: flex;
flex-direction: column;
}
For those who prefer not to set absolutes positions, or can't do it, there is another way to accomplish it: using vh for height of .content:
html,
body {
margin: 0;
padding: 0;
height:100vh;
background: orange;
}
.wrapper {
display: flex;
flex-direction: column;
width: 100%;
height:100vh;
background: pink;
}
.header,
.footer {
height: 10vh;
min-height: 25px; /* (or max-height, or both!) */
max-height: 50px;
background-color: yellow;
flex: 0 0 auto;
}
.footer {
background-color: green;
}
.main {
background-color: cyan;
flex: 1;
display: flex;
flex-direction: column;
height: calc(100vh - 20vh); /* 10vh * 2 (.header + .footer sizes) */
}
.content {
background-color: blue;
color: white;
flex: 1;
display: flex;
flex-direction: column;
height: calc(100vh - 20vh); /* 10vh * 2 (.header + .footer sizes) */
}
.details {
background-color: red;
flex: 1;
display: flex;
flex-direction: column;
}
<div class="wrapper">
<header class="header">Header</header>
<main class="main">
Some text before details
<details class="details" open>
<summary>Details summary</summary>
<div class="content">Details content</div>
</details>
</main>
<footer class="footer">Footer</footer>
</div>
Fiddle's here: http://jsfiddle.net/ALXWebDev/wxm0v49c/
Hope it helps!