I'm trying to tidy up my code and I have a menu that I would like to organise a little better.
Is there a way of aligning the menu at the start, end or or center while having the last item in the menu aligned to the end?
I've currently stripped out everything and kept the basics. If I remove margin-top: auto from the last div, all items are aligned in the center as stated in the .menu css.
If I keep margin-top: auto from the last div, the last div is aligned where I want it but the other items are aligned at the top and not where it's supposed to.
Here's my code:
HTML
<div class="header">
<div class="one">one</div>
<div class="two">two</div>
</div>
<div class="menu">
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
</div>
CSS
.header{
height:70px;
background: red;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-evenly;
}
.header .one {
background: blue;
display: flex;
align-items: center;
padding: 0.5rem 1rem;
}
.header .two {
background: green;
display: flex;
align-items: center;
padding: 0.5rem 1rem;
}
.menu {
width:70px;
height: 100vh;
background: blue;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
}
.three {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.menu div:last-of-type {
margin-top: auto;
}
Here it is in action: Fiddle
Add the following and this will work. You may want to add a padding to match your header, in this case 70px.
.menu {
padding-top: 70px;
}
.menu div {
margin-top: auto;
margin-bottom: auto;
}
.menu div:last-of-type {
margin-top: auto;
margin-bottom: 0;
}
Related
This question already has answers here:
Center and bottom-align flex items
(3 answers)
Closed 4 years ago.
I have a problem with flexbox. I attempted to align two elements; the one to the top of the container, and another one to the center. Most of the flexbox examples were using three elements, not two elements. So I tried my own solution.
#main {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
height: 100px;
background-color: #dfdfdf;
}
#box1 {
display: flex;
justify-content: flex-end;
background-color: #ff0000;
}
#box2 {
display: flex;
background-color: #00ff00;
}
#dummy {
display: flex;
opacity: 0;
}
<div id="main">
<div id="box1">box1</div>
<div id="box2">box2</div>
<div id="dummy">dummy</div>
</div>
...and I also applied it to horizontal case.
#main {
display: flex;
flex: 1;
flex-direction: row;
justify-content: space-between;
height: 100px;
background-color: #dfdfdf;
}
#box1 {
display: flex;
justify-content: flex-end;
background-color: #ff0000;
width: 200px;
}
#box2 {
display: flex;
background-color: #00ff00;
width: 100px;
}
#dummy {
display: flex;
opacity: 0;
width: 200px;
}
<div id="main">
<div id="box1">box1</div>
<div id="box2">box2</div>
<div id="dummy">dummy</div>
</div>
However, it needs a useless dummy element. I think it is not a good idea :(
Is there any better way to solve this?
you don't have to add this 'dummy' div. According to me you should keep display flex in you container, but change justify-content: space-between to justify-content: center.
Then simply add position absolute to you first, child element and display it on the top of the container. Also remember to add relative position to your container.
Here is working code:
#main {
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
height: 100px;
background-color: #dfdfdf;
position: relative;
}
#box1 {
display: flex;
justify-content: flex-end;
background-color: #ff0000;
position:absolute;
top:0;
width:100%;
}
#box2 {
display: flex;
background-color: #00ff00;
}
Fiddle: https://jsfiddle.net/95Lwcbuk/1/
If you want to use flex-box only, you could wrap another .container element around each of your boxes, set these to use flex also, but set the first one to justify-content: flex-start, the last one to justify-content: flex-end.
See example
#main {
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
height: 100px;
background-color: #dfdfdf;
}
.container {
flex-basis:50%;
display:flex;
flex-direction:column;
}
.container:first-child {
justify-content: flex-start;
}
.container:last-child {
justify-content: flex-end;
}
#box1 {
background-color: #ff0000;
}
#box2 {
background-color: #00ff00;
}
<div id="main">
<div class="container">
<div id="box1">box1</div>
</div>
<div class="container">
<div id="box2">box2</div>
</div>
</div>
I'm working on a page that has a header nav, then two rows of banner images, then a couple more divs below the banners.
What I'd like to achieve is to have the nav div be a set height (90px) and then have the two rows of banners evenly split the remaining viewport height of the user's browser. Then, have the two divs below the banners also be fixed pixel heights.
Here's a snippet of my stripped down code:
html, body {
margin: 0;
padding: 0;
}
.nav {
background: red;
height: 90px;
display: flex;
justify-content: center;
align-items: center;
}
.banners-row-1 {
background: green;
display: flex;
justify-content: center;
align-items: center;
height: 50vh;
}
.banners-row-2 {
background: orange;
display: flex;
justify-content: center;
align-items: center;
height: 50vh;
}
.mailing-list {
height: 115px;
background: pink;
display: flex;
justify-content: center;
align-items: center;
}
.footer {
height: 117px;
background: lightblue;
display: flex;
justify-content: center;
align-items: center;
}
<div class="nav">
This is the nav
</div>
<div class="banners-row-1">
Banners Row 1
</div>
<div class="banners-row-2">
Banners Row 2
</div>
<div class="mailing-list">
Mailing List
</div>
<div class="footer">
Footer
</div>
As you can see, the two banner rows are set to 50vh, which is close to what I want - but, is there a way to somehow incorporate the 90px nav div when the banner divs calculate the viewport height?
Essentially, what I'm after is something along the lines of 50% of 'viewport height minus 90px'...?
Thanks
Wrap your nav and banners to wrapper and use following flex properties:
html, body {
margin: 0;
padding: 0;
}
.nav {
background: red;
height: 90px;
display: flex;
justify-content: center;
align-items: center;
}
.wrap {
display: flex;
flex-direction: column;
height: 100vh;
}
.ban {
flex: 1;
}
.banners-row-1 {
background: green;
display: flex;
justify-content: center;
align-items: center;
}
.banners-row-2 {
background: orange;
display: flex;
justify-content: center;
align-items: center;
}
.mailing-list {
height: 115px;
background: pink;
display: flex;
justify-content: center;
align-items: center;
}
.footer {
height: 117px;
background: lightblue;
display: flex;
justify-content: center;
align-items: center;
}
<div class="wrap">
<div class="nav">
This is the nav
</div>
<div class=" ban banners-row-1">
Banners Row 1
</div>
<div class="ban banners-row-2">
Banners Row 2
</div>
</div>
<div class="mailing-list">
Mailing List
</div>
<div class="footer">
Footer
</div>
It works, because space in .wrap is splitted like:
.nav has fixed 90px
.bans have equal left space (100vh - 90px) / 2
This question already has answers here:
White space under image [duplicate]
(5 answers)
Remove white space from image
(3 answers)
Closed 5 years ago.
So I have two divs in a full width container that I want to give variable sizing with flexbox, but no matter what I do, there is an annoying offset at the bottom. Using margins I can come close to fixing the problem, but it's never perfect.
If you run the code snippet below and scroll to the bottom you can see it, the image and the black content container are not aligned at the bottom.
What's going on?
#container {
width: 100%;
display: inline-flex;
flex-direction: row;
}
#image-wrapper {
flex-grow: 3;
max-width: 1000px;
position: relative;
/*background-color: black;*/
}
#menu {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px;
background-color: #101010;
color: #fefefe;
align-items: stretch;
display: flex;
margin-bottom:7px;
}
#form {
width: 100px;
}
#image {
width: 100%;
}
<div id="container">
<div id="image-wrapper">
<img id="image" src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample1_l.jpg"/>
</div>
<div id="menu">
<div id="form">
CONTENT<br>CONTENT<br>
</div>
</div>
</container>
There is some space below the image since the image is an inline-element and as such there is some space reserved below the (invisble) baseline that the image is aligned to vertically. To avoid that, there are two possible solutions:
1.) Apply display: block; to the image (see first snippet)
or
2.) Apply font-size: 0 to the image container (see second snippet)
#container {
width: 100%;
display: inline-flex;
flex-direction: row;
}
#image-wrapper {
flex-grow: 3;
max-width: 1000px;
position: relative;
/*background-color: black;*/
}
img {
display: block;
}
#menu {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px;
background-color: #101010;
color: #fefefe;
align-items: stretch;
display: flex;
}
#form {
width: 100px;
}
#image {
width: 100%;
}
<div id="container">
<div id="image-wrapper">
<img id="image" src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample1_l.jpg" />
</div>
<div id="menu">
<div id="form">
CONTENT<br>CONTENT<br>
</div>
</div>
</div>
SECOND SOLUTION:
#container {
width: 100%;
display: inline-flex;
flex-direction: row;
}
#image-wrapper {
flex-grow: 3;
max-width: 1000px;
position: relative;
/*background-color: black;*/
font-size: 0;
}
#menu {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px;
background-color: #101010;
color: #fefefe;
align-items: stretch;
display: flex;
}
#form {
width: 100px;
}
#image {
width: 100%;
}
<div id="container">
<div id="image-wrapper">
<img id="image" src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample1_l.jpg" />
</div>
<div id="menu">
<div id="form">
CONTENT<br>CONTENT<br>
</div>
</div>
</div>
#container {
width: 100%;
display: inline-flex;
flex-direction: row;
}
#image-wrapper {
flex-grow: 3;
max-width: 1000px;
position: relative;
/*background-color: black;*/
}
#menu {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px;
background-color: #101010;
color: #fefefe;
align-items: stretch;
display: flex;
margin-bottom:4px;
}
#form {
width: 100px;
}
#image {
width: 100%;
}
<div id="container">
<div id="image-wrapper">
<img id="image" src="http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample1_l.jpg"/>
</div>
<div id="menu">
<div id="form">
CONTENT<br>CONTENT<br>
</div>
</div>
</container>
Looks like the margin is just a bit off
I'm trying to create this top header using flexbox.
Basically I would like to center the <div class="header-title"> (Institution institution 1) on the line with the 3 other elements you see. (Institutioner, Ledere and Log ud) like you see on the image.
.nav {
background: #e1e1e1;
}
ol, ul {
list-style: none;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
}
.header-title {
justify-content: center;
align-self: center;
display: flex;
}
.nav ul li.logout {
margin-left: auto;
}
.nav ul li a {
text-decoration: none;
padding: 0px 20px;
font-weight: 600;
}
<div class="nav mobilenav">
<div class="header-title">
Institution institution 1
</div>
<ul>
<li>Institutioner</li>
<li>
Ledere
</li>
<li class="logout">
<a class="button-dark" href="/user/logout">Log ud</a>
</li>
</ul>
</div>
Demo - JSFiddle
Use nested flex containers and flex-grow: 1.
This allows you to create three equal-width sections on the nav bar.
Then each section becomes a (nested) flex container which allows you to vertically and horizontally align the links using flex properties.
Now the left and right items are pinned to the edges of the container and the middle item is perfectly centered (even though the left and right items are different widths).
.nav {
display: flex;
height: 50px; /* optional; just for demo */
background: white;
}
.links {
flex: 1; /* shorthand for: flex-grow: 1, flex-shrink: 1, flex-basis: 0 */
display: flex;
justify-content: flex-start;
align-items: center;
border: 1px dashed red;
}
.header-title {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
border: 1px dashed red;
}
.logout {
flex: 1;
display: flex;
justify-content: flex-end;
align-items: center;
border: 1px dashed red;
}
.links a {
margin: 0 5px;
text-decoration: none;
}
<div class="nav mobilenav">
<div class="links">
Institutioner
Ledere
</div>
<div class="header-title">Institution institution 1</div>
<div class="logout"><a class="button-dark" href="/user/logout">Log ud</a></div>
</div>
jsFiddle
Use justify-content: space-between; like this:
.container {
display: flex;
justify-content: space-between;
}
<div class="container">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
Css grid will do this better than flexbox.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
align-items: center;
}
button {
display: inline-block;
}
.short-content {
margin-left: auto;
}
<div class="grid">
<div class="long-content">
This has content that is fairly long
</div>
<button>CTA Button</button>
<div class="short-content">
Small Text
</div>
</div>
Here is a Flex solution that aligns the right and left containers while centering the middle container correctly.
.header-box {
width: 100%;
display: flex;
flex-flow: row wrap;
padding-top: 50px;
}
.left-header, .center-header, .right-header {
flex: 100px; /* adjust width if needed */
}
.header-box div:nth-of-type(1) {
text-align: left;
}
.header-box div:nth-of-type(2) {
align-self: center;
text-align: center;
}
.header-box div:nth-of-type(3) {
text-align: right;
}
<div class="header-box">
<div class="left-header">Left<br>header<br>content</div>
<div class="center-header">Center<br>header<br>content</div>
<div class="right-header">Right<br>header<br>content</div>
</div>
If you are open to changing your html, you need to put all the items in your header on the same level in the DOM.
Here's a working example
.nav {
background: #e1e1e1;
list-style: none;
display: flex;
align-items: center;
justify-content: space-between;
height: 60px;
}
.nav > div {
min-width: 0;
white-space: nowrap;
}
.header-title {
flex-basis: 80%;
text-align: center;
}
.nav div a {
text-decoration: none;
padding: 0px 20px;
font-weight: 600;
}
<div class="nav mobilenav">
<div>Institutioner</div>
<div>Ledere</div>
<div class="header-title">
Institution institution 1
</div>
<div class="logout">
<a class="button-dark" href="/user/logout">Log ud</a>
</div>
</div>
Is this scenario doable with flex? Cause I can't text-align:center item2 (full width).
<div class="container">
<div class="item1"></div>
<div class="item2"></div>
</div>
EDIT:
I did change the image cause container color was white (as page background)...
You can make both item1 and item2 as display:flex and make justify-content:center and align-items:center that would center the content on those divs
check the snippet
.container {
display: flex;
}
.container div {
background: black;
color: red;
}
.item1 {
width: 50px;
height: 50px;
align-items: center;
display: flex;
justify-content: center;
}
.item2 {
margin-left: 10px;
width: 100%;
height: 70px;
align-items: center;
display: flex;
justify-content: center;
}
<div class="container">
<div class="item1">text</div>
<div class="item2">text</div>
</div>
hope it helps
Here's an example using flex: grow; for .item1 and .item2
CSS:
.container {
display: flex;
flex-wrap: wrap-reverse;
width: 700px;
background-color: black;
padding:33px;
vertical-align:middle;
}
.item1 {
flex-grow: 1;
background: yellowgreen;
height:200px;
margin: 15px;
text-align: center;
display: flex;
align-items: center;
justify-content: center
}
.item2 {
flex-grow: 2;
background: aquamarine;
height:200px;
margin: 15px;
display: inline-block;
text-align: center;
display: flex;
align-items: center;
justify-content: center
}
HTML
<div class="container">
<div class="item1">text</div>
<div class="item2">text</div>
</div>
JSFiddle