Advanced verticalization with flexbox - css

I'm stuck on a Flexbox use case:
I have a horizontal layout for 2 grids with a central (fixed-width ) commands column which allows user to get left grid elements in the right one. See the following scheme:
On a smaller screen, I would like to horizontalize those buttons and not to waste vertical space. See the following scheme:
Anyone would have an idea on how to manage this?

You can simply use flexbox with either the column or row direction, based on the screen width. Use a media query to switch between both views:
.box {
display: flex;
flex-direction: column;
text-align: center;
}
.box div {
border: 1px solid #ddd;
}
button {
width: 100px;
}
#media screen and (min-width: 800px) {
.box {
flex-direction: row;
}
.box :nth-child(1),
.box :nth-child(3) {
flex: 1;
}
.box :nth-child(2) {
flex: 0 1 100px;
}
}
<div class="box">
<div>1</div>
<div>
<button type="button">A</button>
<button type="button">B</button>
<button type="button">C</button>
</div>
<div>3</div>
</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>

Make div's below each other

I have this React code:
const AddPlace = () => {
return (
<div className="split">
<div className="left">
<AddPlaceCard />
</div>
<div className="right" id="map">
<Map />
</div>
</div>
);
}
for large screens this is my CSS:
.split {
display: flex;
flex-direction: raw;
}
.left {
width: 50%;
}
.right {
width: 50%;
}
Large Screen Image:
Now I want a responsive design for mobile which orders the map below the card, I used this code but it didn't help:
#media screen and (max-width: 1000px) {
.split {
display: flex;
flex-direction: column;
}
.left {
width: 100%;
}
.right {
width: 100%;
}
}
Small Screen Image:
You can get away from explicitly setting widths and just use flex grow:1 for each of the child divs - to see the difference - view the snippet in the small snippet window for the small view - and then click the toggle fullScreen button to see the divs sit side by side.
So to explain the code - in both scenarios = the flex-grow: 1 on the child divs causes it to expand to fill the available space - and because there are two divs - this will cause a 50% / 50% split (same deal if there are 3 divs - they will take up equal thirds of the available space).
So the only difference then between the normal and the media-query is which direction do they grow in. Since the default direction is "row" you do not really even need to include that in the initial styling - I included it to demontrate the point in this snippet.
In flex direction: row: - flex-grow: 1 will cause a horizontal expansiosion and in flex-direction: column - it is a vertical expansion.
Also - note that by applying height: 100% to the html, body, and .split - each div takes the entire height available.
html {
height: 100%;
}
body {
height: 100%;
margin:0
}
.split {
display: flex;
flex-direction: row;
height: 100%;
}
.split div {
flex-grow:1;
padding: 16px
}
.left {
border: solid 1px red;
}
.right {
border: solid 1px blue;
}
#media screen and (max-width: 1000px) {
.split {
flex-direction: column;
}
}
<div class="split">
<div class="left">
<p> This is the div for the placecard</p>
</div>
<div class="right" id="map">
<p> This is the div for the map</p>
</div>
</div>

Using Flex - change two child div's to stack on each other with 100% width

I want the two child div's to justify to the left and stack on each other 100% width at a certain browser media width of 1000px.
I have two child div's in a parent that appear correctly:
.relationFRAME {
background: #151515;
color: #FFF;
display: flex;
}
.relationLEFT {
width: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.relationRIGHT {
float: right;
flex: 1;
}
I want the two child div's to justify to the left and stack on each other 100% width at a certain browser media width of 1000px.
Can someone help me understand the change in the CSS to do this?
With #media you can change the styling at an certain width and flex-direction: column; to stack the child elements on top of each other.
Here's an example:
.relationFRAME {
background: #151515;
display: flex;
}
.relationLEFT {
background: green;
flex: 1;
}
.relationRIGHT {
background: orange;
flex: 1;
}
#media only screen and (max-width: 1000px) {
.relationFRAME {
flex-direction: column;
}
}
<div class="relationFRAME">
<div class="relationLEFT">a</div>
<div class="relationRIGHT">b</div>
</div>
You can set a min-width to the child and allow wrapping on the parent :
.relationFRAME {
background: #151515;
display: flex;
flex-wrap:wrap;/* will stack element if width becomes too small */
}
.relationFRAME > div {
flex:1;
min-width:580px;/* whatever value you want to set as a break point */
/* demo use only */
border:1px solid ;
color:white;
margin:2px;
padding:0.25em;
}
<div class="relationFRAME">
<div class="relationLEFT"> Play me full page mode and resize window to check out my behavior </div>
<div class="relationRIGHT">b</div>
</div>

Flexbox grid: How to display 3 items side-by-side but varying vertical positions

The red boxes are the items, the grey background is the container:
I have 3 items that I want to display in a container. Please see the included image.
What is the best way to go about this using flexbox? It should be the same on mobile view.
Thanks
Use flexbox, with nth-child to change the specific heights of the flex objects.
EX:
//HTML
<div class="container">
<div class="flex"></div>
<div class="flex"></div>
<div class="flex"></div>
</div>
//CSS
.container{
background: #AAA;
border: 1px solid black;
display: flex;
height: 15vw;
width: 20vw;
}
.flex{
background: #F00;
height: 7vw;
margin-left: 1.25vw;
width: 5vw;
}
.flex:nth-child(1){
margin-top: 6vw;
}
.flex:nth-child(2){
margin-top: 1vw;
}
.flex:nth-child(3){
margin-top: 5vw;
}
See an example here:
https://jsfiddle.net/mn8ukbae/7/
with flex you have the align-self property, which can be used to align an element on the cross-axis differently from the others, within the same flex parent.
.container { display: flex; }
.item--1 { align-self: flex-end; }
.item--2 { align-self: flex-start; }
.item--3 { align-self: center; }
I could almost bet my life that this is a 'homework' exercise, and you would do well to read up on flex and align-self to make the most of it.

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

Resources