Position an element x% of a way along with flexbox? - css

I want to position an element so that of the available space, 1/3 is above it and 2/3 are below. This is a React Native project so I can use flexbox but not grid or floats.
This code works but it's not very clean having to have empty elements div.first and div.last, can it be done without them?
body {
display: flex;
flex-direction: column;
height: 100vh;
}
.one {
background: gold
}
.first {
flex: 1;
}
.last {
flex: 2
}
<div class="first"></div>
<div class="one">One</div>
<div class="last"></div>
https://codepen.io/adsfdsfhdsafkhdsafjkdhafskjds/pen/PoPjdad

How about using margin like this?
Edit: Just add overflow-y:hidden; to body
body {
display: flex;
flex-direction: column;
height: 100vh;
overflow-y:hidden;
}
.one {
background: gold;
margin:33vh 0 66vh 0;
}
<div class="one">One</div>

Related

Three div / two column layout - possible with Flexbox?

I've been trying to achieve the layout below using flexbox. I originally had a left hand sidebar containing the image & navigation, and a main content area. On mobile, the sidebar used to wrap under the main content.
The problem with that is that I need the image to remain at the top on mobile, so I've been trying with three sibling divs in one wrapper div.
Is this even possible with flexbox or will I need to use css grid?
Although CSS Grid would be the best approach to achieve the lay-out you want, it is possible using CSS Flexbox.
You just have to create a wrapper div with three divs inside (when doing a mobile first approach) and with .content set to flex: 1 to stretch out the height of your viewport.
Then for desktop (in this case #media screen and (min-width: 1000px)), change the order (MDN reference of order) of .navigation and .content and give all three divs appropriate widths according to their needs. The only change to div.wrapper is that it needs flex-flow: column wrap to wrap correctly.
.wrapper {
display: flex;
flex-direction: column;
height: 100%;
min-height: 100%;
}
.box {
display: flex;
}
.content {
flex: 1;
}
#media screen and (min-width: 1000px) {
.wrapper {
flex-flow: column wrap;
}
.navigation {
order: 2;
}
.content {
order: 3;
}
.image,
.navigation {
width: 200px;
flex: 50%;
}
.content {
width: calc(100% - 200px);
flex: 0 0 100%;
}
}
/* Generic styling */
html,
body {
height: 100%;
}
body {
margin: 0;
padding: 0;
}
.image {
background: orange;
height: 60px;
}
.content {
background: lightblue;
}
.navigation {
background: lightgreen;
height: 60px;
}
<div class="wrapper">
<div class="box image">Image</div>
<div class="box content">Content</div>
<div class="box navigation">Navigation</div>
</div>

Resize flex item based on its content

Sorry, another flexbox related question :)
I have two flex elements :
A container (red) containing a centered div (yellow)
A footer (blue) with an undefined height
The red container has a flex-grow:1 attribute, forcing it to take the remaining space on the screen
The issue happens when the yellow element is bigger than the screen size. I would like my red container to grow based on its content. Any idea of how I could do that ?
HTML:
<div class="container">
<div class="content"></div>
</div>
<div class="footer"></div>
CSS:
body,
html {
margin: 0;
height: 100%;
display: flex;
flex-direction: column;
}
.container {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: center;
background: red;
}
.content {
background: yellow;
height: 2000px;
width: 100px;
}
.footer {
flex-shrink: 0;
height: 50px;
background-color: blue;
}
https://codepen.io/stepinsight/pen/roRVGQ
== EDIT ==
Andre helped me find the answer, thanks heaps !
The only thing you need to change in the code above is to replace height by min-height and the % by vh for the body/html tags 🎉
body,
html {
margin: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
}
Simply remove the height property on the body element and add height: 100% to html
* { box-sizing: border-box; }
html {
height: 100%
}
body {
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
}
.container {
display: flex;
align-items: center;
justify-content: center;
background: red;
}
.content {
background: yellow;
height: 2000px;
width: 100px;
}
.footer {
height: 50px;
background-color: blue;
}
Corrected: https://codepen.io/ferreirandre/pen/maoVvb
Feel free to play around with the height of .content

calculate remaining height using CSS calc()

I need the .content div use all the available space
body {
height: 100%;
}
.nav {
padding: 20px;
}
.content {
height: 100%;
}
<body>
<div class="nav">nav</div>
<div class="content">content</div>
</body>
Since I don't know the height of the .nav I can't use height: calc(100%-Xpx)
is there any other way to make .content use the remaining height of the page?
Thanks
Use min-height: 100vh on body, then set the parent (body in this case) to display: flex; flex-direction: column and use flex-grow: 1 on .content for it to use the available space.
body {
min-height: 100vh;
display: flex;
flex-direction: column;
margin: 0;
}
.nav {
padding: 20px;
}
.content {
flex-grow: 1;
background: #eee;
}
<div class="nav">nav</div>
<div class="content">content</div>

Keeping a child div from expanding a flexbox div

Well, here on this fiddle I have two divs aligned with display:flex and flex-grow: https://jsfiddle.net/h7bm23ts/2/
window.longer = function() {
document.getElementsByClassName("child2")[0].innerHTML += "like this and ";
};
* {
font-family: sans-serif;
}
.wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.box1 {
background-color: beige;
height: 300px;
flex-grow: 2;
}
.box2 {
background-color: cyan;
height: 300px;
flex-grow: 1;
}
.child1 {
background-color: green;
}
.child2 {
background-color: gray;
}
<div class="wrapper">
<div class="box1">
some nonsense
</div>
<div class="box2">
longer nonsense <button onclick="window.longer();"> even longer </button>
<div class="child1">
this child should be able to expand this div
</div>
<div class="child2">
this child should wrap when too much content is appended
</div>
</div>
</div>
However, the content in one of the divs is dynamic and when more content is appended onto a child div of it, the parent div expands and makes the boxes wrap, ruining the layout with a few button clicks.
How do I keep the gray div from expanding on more content and make it simply accept its parent's width as "strict" and wrap in it?
EDIT: I settled on https://jsfiddle.net/h7bm23ts/12/.
Try this css to achive what you need:
.wrapper {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.box1 {
background-color: beige;
min-height: 300px;
flex: 2 1 0; /* 2 - flex grow, 1 - flex shrink, 0 - flex basis */
}
.box2 {
background-color: cyan;
min-height: 300px;
flex: 1 0 0;
}
More about this You can find here:
https://css-tricks.com/flex-grow-is-weird/ and here: https://drafts.csswg.org/css-flexbox/#flex-grow-property, and
https://drafts.csswg.org/css-flexbox/#flexibility

Firefox ignores width property of element when using flex

I am trying to align some elements using different flex and width properties. In Safari and Chrome the behavior is as expected, but in firefox it is not.
It seems that the width property gets ignored, even though you set the width of the element to a very high, fixed value.
See example here:
https://jsfiddle.net/wugrtwjc/
The desired behavior is to have the two divs wrapped in the class "r-6" under each other, both covering the whole width of their parent (This is happening in Firefox and Chrome).
In firefox the two divs is aligned next to each other even though the width is set to 100%. You can also try to set the width of this class to something like 10000px, but it will still only take up half of the space of its parent div.
Html setup:
<div class="layout-row">
<div class="c-l-8">
<div class="layout-col h-800">
<div class="r-6">
<div class="one"></div>
</div>
<div class="r-6">
<div class="two"></div>
</div>
</div>
</div>
</div>
CSS:
.layout-row {
-webkit-flex-flow: row wrap;
width: 100%;
}
.layout-col {
-webkit-flex-flow: column wrap;
}
.layout-row, .layout-col {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.c-l-8 {
width: 66.66667%;
}
.r-6 {
width: 100%;
height: 50%;
}
.h-800 {
height: 800px;
}
.one, .two {
width: 100%;
height: 100%;
}
.one {
background: red;
}
.two {
background: blue;
}
try this code
<style>
.layout-row,
.layout-col {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.layout-row {
flex-flow: row wrap;
width: 100vw;
}
.layout-col {
flex-flow: column wrap;
}
.c-l-8 {
width: 100%;
}
.r-6 {
width: 100%;
height: 50%;
}
.h-800 {
height: 800px;
}
.one,
.two {
width: 100%;
height: 100%;
}
.one {
background: red;
}
.two {
background: blue;
}
</style>
Hope this helps..
Take care and happy coding

Resources