How to align cascaded div containers with Flexbox - html

I am trying to achieve the following layout for a navigation bar with Flexbox. I am stuck with the alignment of the divs. This is how it should like:
This is what i build up with Divs and CSS. But i dont know how to align those divs, so that i get the desired result.
Fiddle
* {
box-sizing: border-box;
}
#nav {
display: flex;
}
#logo {
width: 100px;
heigth: 100px;
background-color: black;
margin-left: 24px;
}
<div id="nav">
<div id="logo">
100x100px Logo
</div>
<div id="left_side">
<div id="top_nav">
<div id="title">TITLE OF PAGE</div>
<div id="menu_swith">SWITCH</div>
</div>
<div id="bottom_nav">
<div class="nav_item">Menu 1</div>
<div class="nav_item">Menu 2</div>
<div class="nav_item">Menu 3</div>
<div class="nav_item">Menu 4</div>
</div>
</div>
</div>

I would add a few more flex containers to some of the child divs. I'd also specify the width and flex-direction on the #left_side div and justify the content on the #top_nav div.
Try the snippet below or see this updated fiddle:
* {
box-sizing: border-box;
}
#nav,
#left_side,
#top_nav,
#bottom_nav {
display: flex;
}
#left_side {
flex-direction: column;
width: 100%;
}
#top_nav {
justify-content: space-between;
}
#logo {
width: 100px;
heigth: 100px;
background-color: black;
margin-left: 24px;
}
<div id="nav">
<div id="logo">
100x100px Logo
</div>
<div id="left_side">
<div id="top_nav">
<div id="title">TITLE OF PAGE</div>
<div id="menu_swith">SWITCH</div>
</div>
<div id="bottom_nav">
<div class="nav_item">Menu 1</div>
<div class="nav_item">Menu 2</div>
<div class="nav_item">Menu 3</div>
<div class="nav_item">Menu 4</div>
</div>
</div>
</div>

There are many good guides to flexbox available. This one is very good: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Your layout can be achieved by adding the following CSS
fiddle
* {
box-sizing: border-box;
}
#nav {
display: flex;
}
#logo {
width: 100px;
height: 100px;
background-color: black;
margin-left: 24px;
}
#left_side {
display: flex;
flex-direction: column;
flex: 1;
}
#top_nav {
display: flex;
justify-content: space-between;
flex: 1;
}
#bottom_nav {
display: flex;
flex: 1;
}
<div id="nav">
<div id="logo">
100x100px Logo
</div>
<div id="left_side">
<div id="top_nav">
<div id="title">TITLE OF PAGE</div>
<div id="menu_swith">SWITCH</div>
</div>
<div id="bottom_nav">
<div class="nav_item">Menu 1</div>
<div class="nav_item">Menu 2</div>
<div class="nav_item">Menu 3</div>
<div class="nav_item">Menu 4</div>
</div>
</div>
</div>

Flexbox is one way to build the layout. You'll need extra containers to make it work.
However, if you want to keep it really simple, use CSS Grid:
header {
display: grid;
grid-template-columns: 100px 3fr 1fr;
grid-template-rows: 50px 50px;
grid-template-areas: " logo title switch "
" logo nav nav ";
}
#logo { grid-area: logo; }
#title { grid-area: title; }
#menu_switch { grid-area: switch; }
nav { grid-area: nav; display: flex; }
nav > a {
flex: 0 0 75px;
margin: 5px;
border: 2px solid green;
}
/* for demo only */
#logo { background-color: lightgray; }
#title { background-color: pink; }
#menu_switch { background-color: skyblue; }
nav { background-color: lightgreen; }
* { box-sizing: border-box; }
div, a { display: flex; align-items: center; justify-content: center;
text-align: center; }
<header>
<div id="logo">100x100px<br>Logo</div>
<div id="title">Page Title</div>
<div id="menu_switch">Switch</div>
<nav>
<a class="nav_item">Menu 1</a>
<a class="nav_item">Menu 2</a>
<a class="nav_item">Menu 3</a>
<a class="nav_item">Menu 4</a>
</nav>
</header>
jsFiddle demo
For an explanation of the grid rules above and browser support data, see these posts:
CSS-only masonry layout but with elements ordered horizontally
Browser support for CSS Grid

Related

How to get nested css flex to have the right width after wrap in this setup?

I have this mockup, there are some nested containers. some of the link-class have multiple elements (par and ref) and I want them to display next to each other if there's space, but responsively move them below each other when total width gets smaller.
It works somewhat, but I expect (want) the link-element containing two childs to return to the same width as the link-element with one single child as it wraps.
For some reason, it remains wider than the single-child ones.
Any hints appreciated!
Code:
let name = 'world';
:global(body) {
margin: 0;
padding: 0
}
.main {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
background-color: gray;
}
.Container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: lightblue;
padding: 3px
}
.linkContainer {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 3px;
background-color: salmon;
}
.par {
width: 80vw;
max-width: 300px;
background-color: red
}
.links {
display: flex;
flex-flow: row wrap;
padding: 3px;
background-color: orange
}
.ref {
background-color: olive;
width: 30vw;
max-width: 100px
}
.item {
width: 80vw;
max-width: 300px;
background-color: steelblue
}
<div class="main">
<div class="Container">
<div class="item">
header
</div>
<div class="linkContainer">
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="Container">
<div class="item">
another header
</div>
<div class="linkContainer">
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
</div>
</div>
</div>
</div>
</div>
you could simply add a max-width:300px; to .links and have the box in size but then you couldn't have the desired stacking effect you wanted so i went a bit further and with the help of css variables and media queries and adding a class .single to single .pars which didn't have a .ref after them, i came up with this:
:root {
--ref-size: 100px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.main {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
background-color: gray;
}
.Container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: lightblue;
padding: 3px
}
.links {
min-width: 300px;
display: flex;
flex-flow: row wrap;
padding: 3px;
background-color: orange;
}
.par {
width: calc(100% - var(--ref-size));
background-color: red;
}
.ref {
background-color: olive;
width: var(--ref-size);
}
.item {
width: 80vw;
max-width: 300px;
background-color: steelblue
}
#media all and (max-width:300px){
.par{
width: 100%;
}
}
#media all and (min-width: 300px){
.par.single{
width: 100%;
}
}
<div class="main">
<div class="Container">
<div class="item links">
header
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="item links">
another header
</div>
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
<div class="links">
<div class="par single">
some text
</div>
</div>
<div class="links">
<div class="par">
some text
</div>
<div class="ref">
a ref
</div>
</div>
</div>
</div>

Creating a layout with Flexbox

hey I'm new in Flexbox and I'm trying to get it as best as I can. However i faces a problem with some heights and orders, maybe some here could help out.
Note: Don't suggest using Grid/tables please.
this is what I have right now:
this is what I want to get:
html:
<div class="movie-container">
<div class="upper-container">
<div class="image">Image</div>
<div class="title">Title</div>
<div class="more">More</div>
</div>
<div class="lower-container">
<div class="runtime">Runtime</div>
<div class="description">Description</div>
<div class="director">Director</div>
</div>
</div>
css:
.movie-container{
display:flex;
flex-flow: column wrap;
}
.upper-container {
display: flex;
width:80%;
margin:0 auto;
flex-flow: raw wrap;
}
.upper-container div {
border: 1px solid black;
padding: 10px;
}
.lower-container {
display: flex;
width:80%;
margin:0 auto;
flex-flow: column wrap;
}
.lower-container div {
border: 1px solid black;
padding: 10px;
}
.image {
flex: 1;
}
.title {
flex: 3;
}
.more {
flex: 0.1;
}
.runtime{
}
.description{
}
.director{
}
Maybe other stuff need to be added beside flexbox I'm not sure, that's why I ask here. Any solution will be helpful!
If you change your HTML structure slightly you can accomplish this fairly easily:
<div class="movie-container">
<div class="upper-container">
<div class="image">Image</div>
<div class="side-container">
<div class="title">Title</div>
<div class="more">More</div>
<div class="runtime">Runtime</div>
<div class="description">Description</div>
</div>
</div>
<div class="lower-container">
<div class="director">Director</div>
</div>
</div>
JSFiddle
Flex isn't very good at stretching across multiple rows / columns like tables or Grid is, while you state you don't want that solution it is typically a better option in cases like this.
I find it easiest to work with flexbox on a row-by-row basis instead of using wrapping (although you can certainly do that too).
As a starting point, I think this snippet is what you're going for?
div {
flex: 1 1 auto;
}
.box {
border: 1px solid black;
}
.flex {
display: flex;
}
.image {
width: 120px;
flex: 0 0 auto;
}
.more {
flex: 0 0 auto;
}
<div class="flex upper">
<div class="box flex image">Image</div>
<div class="upper-detail">
<div class="flex title-container">
<div class="box title">Title</div>
<div class="box more">More</div>
</div>
<div class="box runetime">Runtime</div>
<div class="box director">Director</div>
</div>
</div>
<div class="box description">Description</div>
<div class="box other">Other stuff...</div>
Hope this helps.
.upper-container{
display: flex;
height: 200px;
}
.upper-left{
background: #ddd;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.upper-right{
flex: 3;
display: flex;
flex-direction: column;
height: 100%;
}
.title-more, .runtime, .director{
flex: 1;
border: 1px solid #222;
display: flex;
align-items: center;
}
.lower-container{
border: 1px solid #222;
padding: 10px;
}
.title-more{
justify-content: space-between;
}
.more-button{
height: 30px;
width: 100px;
border: 1px solid #333;
margin-right: 5px;
display: flex;
align-items: center;
justify-content: center;
}
<div class="movie-container">
<div class="upper-container">
<div class="upper-left">
Image
</div>
<div class="upper-right">
<div class="title-more">
<div class="title-container">
Title
</div>
<div class="more-button">
More
</div>
</div>
<div class="runtime">Runtime</div>
<div class="director">Director</div>
</div>
</div>
<div class="lower-container">
Description
</div>
</div>
The key is to add some divs and remove some others:
.movie-container *{padding:.5em;}
.upper-container {
display: flex;
padding:0;
}
.image {
border: 1px solid;
flex: 1 1 25%;
}
.tmrd{flex: 1 1 75%;padding:0}
.title-more {
display: flex;
padding:0;
}
.title{flex: 1 1 75%;border: 1px solid;}
.more{flex: 1 1 25%;border: 1px solid;}
.runtime,.description,.director{border: 1px solid;}
<div class="movie-container">
<div class="upper-container">
<div class="image">Image</div>
<div class="tmrd">
<div class="title-more">
<div class="title">Title</div>
<div class="more">More</div>
</div>
<div class="runtime">Runtime</div>
<div class="description">Description</div>
</div>
</div>
<div class="director">Director</div>
</div>

Display 2 div in block and vertical div beside them

I am trying to design a section which 3 image. I can get the two images to display by block easily. I can float the third image to the right and adjust the height easily. However my issue is it does not align side by side.Below is an example of what I am trying to achieve
This is an example of what I have so far
.image-one,
.image-two {
width: 250px;
background-color: green;
display: block;
margin-top: 10px;
}
.image-three {
float: right;
background-color: lightblue;
width: 250px;
height: 200px;
}
<div class="container">
<div class="image-one">Hello</div>
<div class="image-two">Image two</div>
<div class="image-three"> Image three </div>
</div>
You should be able to simple add flex to the container, and then add the content within a left and a right div.
Here's a working example:
.container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.image-one,
.image-two {
width: 250px;
height: 95px;
background-color: green;
margin-bottom: 10px;
}
.image-three {
background-color: lightblue;
width: 240px;
height: 200px;
margin-left: 10px;
}
<div class="container">
<div class="left">
<div class="image-one">Hello</div>
<div class="image-two">Image two</div>
</div>
<div class="right">
<div class="image-three"> Image three </div>
</div>
</div>
You can use flexbox for this:
.container {
display: flex;
flex-direction: column; /* align items in columns */
flex-wrap: wrap; /* wrap to a new column when height is reached */
justify-content: space-between; /* add spacing in between top and bottom image */
height: 210px; /* height of your 2 images plus and spacing you want */
width: 510px; /* width of 2 columns plus any spacing */
}
.image-one,
.image-two {
width: 250px;
height: 100px;
background-color: green;
display: block;
}
.image-three {
background-color: lightblue;
width: 250px;
height: 210px; /* I would make this image the height of the other 2 plus spacing */
align-self:flex-end; /* align this to the right of the container */
}
<div class="container">
<div class="image-one">Hello</div>
<div class="image-two">Image two</div>
<div class="image-three"> Image three </div>
</div>
Maybe you can add some internal divs like this:
<div class="container">
<div class="container-left">
<div class="image-one">Hello</div>
<div class="image-two">Image two</div>
</div>
<div class="container-right">
<div class="image-three"> Image three </div>
</div>
</div>
Then, add css to container-left and container-right to properly set the width and the float. Like this:
.container-left, .container-right{
width:250px;
float:left;
}
Why don't you make use of bootstrap columns?
HTML
<div class="container">
<div class="row main-row">
<div class="col-6 left-col">
<div class="row left-col-top">
<!-- Top left image here -->
</div>
<div class="row left-col-bottom">
<!-- Bottom left image here -->
</div>
</div>
<div class="col-6 right-col">
</div>
</div>
</div>
CSS
.main-row {
height:300px;
}
.left-col-top {
background-color:blue;
height:50%;
}
.left-col-bottom {
background-color:red;
height:50%;
}
.right-col {
background-color:green;
height:100%;
}
Easy flexbox solution :)
#main, #left {
display:flex;
}
#left {
flex-direction: column;
flex: 1;
}
.section {
flex: 1;
margin: 2px;
background-color: green;
}
<div id="main">
<div id="left">
<div class="section">Hello</div>
<div class="section">Hello</div>
</div>
<div id="right" class="section">Hello</div>
</div>

Place span inside div on bottom

folks!
there is a problem layouting my page header :/
i want to place the logo and title on the left, and some usermenu/logout/messages on the right.
html:
<div class="banner">
<img class="logo" src="data:image/gif;base64,R0lGODdhMgAyAPQAAL7ikLjfh+r12q3adNTstfr99u/45OTz0fT67c7prMPkmbPdftnuv8nno9/wyP///6jYawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAMgAyAAAF5iAkjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IpHLJvAUGvIBK8Kg+AJAAtUCIAaxVUQLxEGBPgi7JcMg+GrBvKfBQQBgFVLpUFxnUIwYGAwMIbSRyJAkPIl9SJlQPXCJXIgICJQsFDgeDJV9VCFIEmBADlSZPAwwPUqiXJl8FjyQDUgEGmKQip2cplX0Qf7GStCcEjIuNrScNUMhSbG5wJJqkCFCIWAMCbXR2eChgalqSgIGYAwWHI4uhj2MPBnYnAwAAC3PZMQv3qU0AAwocSLCgwYMIEypcyLChw4cQl4QAADs=">
<div class="title">foo</div>
<div class="logout">bar</div>
</div>
<div class="content">
Some Content..
</div>
css:
.banner {
height: 50px;
background-color: #feefef;
}
.img, .title, .logout{
vertical-align: text-bottom;
height:100%;
}
.logo {float: left;}
.title {float:left;}
.logout {float:right;}
https://jsfiddle.net/z9gervtm/3/
How do i move those texts to the bottom?
use flexbox to simplify your code
.banner {
height: 50px;
background-color: #feefef;
display: flex;
justify-content: space-between;
align-items: flex-end
}
.left {
display: flex;
align-items: flex-end
}
<div class="banner">
<div class="left">
<img class="logo" src="data:image/gif;base64,R0lGODdhMgAyAPQAAL7ikLjfh+r12q3adNTstfr99u/45OTz0fT67c7prMPkmbPdftnuv8nno9/wyP///6jYawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAMgAyAAAF5iAkjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IpHLJvAUGvIBK8Kg+AJAAtUCIAaxVUQLxEGBPgi7JcMg+GrBvKfBQQBgFVLpUFxnUIwYGAwMIbSRyJAkPIl9SJlQPXCJXIgICJQsFDgeDJV9VCFIEmBADlSZPAwwPUqiXJl8FjyQDUgEGmKQip2cplX0Qf7GStCcEjIuNrScNUMhSbG5wJJqkCFCIWAMCbXR2eChgalqSgIGYAwWHI4uhj2MPBnYnAwAAC3PZMQv3qU0AAwocSLCgwYMIEypcyLChw4cQl4QAADs=">
<div class="title">foo</div>
</div>
<div class="logout">bar</div>
</div>
<div class="content">
Some Content..
</div>
I would just use flexbox and get rid of the floats. Add divs to have a left and right banner section. Align-items center to make it look nice:
.banner {
display: flex;
justify-content: space-between;
height: 50px;
padding: 0 20px;
background-color: #feefef;
}
.left {
display: flex;
align-items: center;
}
.right {
display: flex;
align-items: center;
}
.left img,
.right div:first-of-type {
margin-right: 10px;
}
<div class="banner">
<div class="left">
<img class="logo" src="data:image/gif;base64,R0lGODdhMgAyAPQAAL7ikLjfh+r12q3adNTstfr99u/45OTz0fT67c7prMPkmbPdftnuv8nno9/wyP///6jYawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAMgAyAAAF5iAkjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IpHLJvAUGvIBK8Kg+AJAAtUCIAaxVUQLxEGBPgi7JcMg+GrBvKfBQQBgFVLpUFxnUIwYGAwMIbSRyJAkPIl9SJlQPXCJXIgICJQsFDgeDJV9VCFIEmBADlSZPAwwPUqiXJl8FjyQDUgEGmKQip2cplX0Qf7GStCcEjIuNrScNUMhSbG5wJJqkCFCIWAMCbXR2eChgalqSgIGYAwWHI4uhj2MPBnYnAwAAC3PZMQv3qU0AAwocSLCgwYMIEypcyLChw4cQl4QAADs=">
<div class="title">Title</div>
</div>
<div class="right">
<div class="logout">Logout</div>
<div class="messages">Messages</div>
</div>
</div>
<div class="content">
Some Content..
</div>

Flexbox items of same size

How can I force flexbox items to have same height.
In examples I found online, people are using align-items: stretch css property, but my example is more complex.
Here is a codepen example:
.container {
background-color: red;
display: flex;
align-items: stretch;
}
.boxes {
background-color: yellow;
margin: 5px;
display: flex;
}
.boxes-column {
flex-direction: column;
}
.box {
background-color: green;
width: 100px;
margin: 5px;
}
.heading {
background-color: pink;
}
<body>
<div class="container">
<div class="boxes boxes-column">
<div class="heading">This is heading</div>
<div class="boxes">
<div class="box">Content content content content content content content</div>
<div class="box">Content content</div>
<div class="box">Content</div>
<div class="box">Contento contento</div>
<div class="box">Cc</div>
<div class="box">Contetno contento contento</div>
</div>
</div>
<div class="boxes boxes-column">
<div class="heading">This is heading 2</div>
<div class="boxes">
<div class="box">Content</div>
<div class="box">Contentno Contetn</div>
<div class="box">C</div>
</div>
</div>
</div>
</body>
Height of items items below 'Heading' and height of items below 'Heading 2' should be equal.
Used this css and now the boxes have the same height:
.container > .boxes > .boxes {
flex: 1;
}
Take a look at the below snippet:
.container {
background-color: red;
display: flex;
align-items: stretch;
}
.boxes {
background-color: yellow;
margin: 5px;
display: flex;
}
.boxes-column {
flex-direction: column;
}
.box {
background-color: green;
width: 100px;
margin: 5px;
}
.heading {
background-color: pink;
}
.container > .boxes > .boxes {
flex: 1;
}
<body>
<div class="container">
<div class="boxes boxes-column">
<div class="heading">This is heading</div>
<div class="boxes">
<div class="box">Content content content content content content content</div>
<div class="box">Content content</div>
<div class="box">Content</div>
<div class="box">Contento contento</div>
<div class="box">Cc</div>
<div class="box">Contetno contento contento</div>
</div>
</div>
<div class="boxes boxes-column">
<div class="heading">This is heading 2</div>
<div class="boxes">
<div class="box">Content</div>
<div class="box">Contentno Contetn</div>
<div class="box">C</div>
</div>
</div>
</div>
</body>