Set child of flex element to be height of parent? - css

JSFiddle
I wish to have a to the left and b to the right. In the center is a list aligned horizontally. I want the full-height div to be the height of the parent.
So:
a 1 2 3 b
Here's the HTML:
<div class="container">
<div class="a">
a
</div>
<div class="full-height">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
<div>
b
</div>
</div>
I've looked at other SO posts which have 2 solutions:
Add flex-direction: column; to the parent. Which won't work in this situation as parent needs to be horizontally laid out.
Set parent height and make child height: 100%. I need the parents height to be dynamic.
Any ideas?

You need to use align-self:stretch; on the .full-height element.
To align elements inside the list I added:
align-items: center;
display: flex;
justify-content: center;
to the .full-height and a, also removed the padding from the ul.
UPDATE 1:
Updated to meet the comment. Moved flex content to ul instead of .full-height and added height 100% to ul.
You can read more about how flex works in this article.
.container{
display: flex;
position: static;
width: 100%;
background: gold;
align-items: center;
justify-content: space-between;
}
.a{
height: 300px;
align-items: center;
display: flex;
justify-content: center;
}
ul{
list-style-type: none;
}
li{
display: inline-block;
}
.full-height{
background: tomato;
align-self: stretch;
}
ul{
height:100%;
align-items: center;
display: flex;
justify-content: center;
padding:0;
margin:0;
}
<div class="container">
<div class="a">
a
</div>
<div class="full-height">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
<div>
b
</div>
</div>

Related

Navbar position

I am currently working on building my photography portfolio site.
I try to position my navbar under my logo, but I can't match the navbar to the size and the postion of the logo.
any idea how can I position my nav using CSS?
Thanks
Quick fix. Hero is de flexbox
header {
width: 100%;
display: flex;
flex-wrap: wrap;
}
.logo,
nav {
width: inherit;
text-align: center;
}
ul {
list-style: none;
width: inherit;
display: flex;
justify-content: space-between;
}
<header>
<div class="logo"><img src="https://via.placeholder.com/300x100"></div>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
</nav>
</header>

align-content: center not working in Chrome

I am trying to vertically align divs with flexbox, by using the align-content: center. It works fine in Firefox and IE, but it does not vertically align in Chrome. In Chrome the divs stays on top.
<div class="products-wrapper">
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
</div>
And CSS:
.products-wrapper {
width: 100%;
min-height: 100vh;
/* FLEX */
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-content: center;
}
.product {
max-width: 250px;
padding: 10px;
}
.product img {
display: block;
margin: 0 auto;
max-height: 250px;
max-width: 250px;
}
I have also been trying align-items: center; which centers the divs vertically, but it will not be a straight line with the images and text if I have different amount of text for example.
Anyone with a solution how to vertically center divs (straight), which works in all browsers?
Image example:
Edit: If you don't need the height to be dynamic, align-items: center; will work with (for example) max-height: 400px; on the .product div. Not really what I wanted though.
In order to achieve what you want you'll need to use align-items: flex-start, this way all items will be aligned to the top of their line. And to center vertically you're looking for the align-items: center property which aligns the items in the flex container along the cross axis, which in your case you'll have to use in an outer wrapper to make sure the products div is centered in the page.
The align-content: center property comes into play only when there is more than one line (wrapped content).
A better explanation about the difference between those two properties is in the answer to this stackoverflow question
.outer-wrapper {
width: 100%;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.products-wrapper {
width: 100%;
/* FLEX */
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
background-color: gray;
align-items: flex-start;
}
.product {
max-width: 250px;
padding: 10px;
background-color: red;
margin: 5px;
}
.product img {
display: block;
margin: 0 auto;
max-height: 250px;
max-width: 250px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="outer-wrapper">
<div class="products-wrapper">
<div class="product">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/St._Bernard_puppy.jpg/120px-St._Bernard_puppy.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/St._Bernard_puppy.jpg/120px-St._Bernard_puppy.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/71/St._Bernard_puppy.jpg/120px-St._Bernard_puppy.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
</div>
</div>
</body>
</html>
Make the .product element, flex container. This so you can align the content inside them.
.product {
max-width: 250px;
padding: 10px;
display: flex;
justify-content: center;
flex-direction: column;
}
Hope this helps :)
.products-wrapper {
width: 100%;
min-height: 100vh;
/* FLEX */
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-content: center;
}
.product {
max-width: 250px;
padding: 10px;
display: flex;
justify-content: center;
flex-direction: column;
}
.product img {
display: block;
margin: 0 auto;
max-height: 250px;
max-width: 250px;
}
<div class="products-wrapper">
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
<div class="product">
<img src="images/temporary.jpg" alt="Temporary">
<h3>Title</h3>
<p>Text.</p>
</div>
</div>

flexbox vertical align child top, center another

I've got the following markup:
.row {
display: flex;
align-items: stretch;
margin: -16px;
background: #ddd;
}
.row .col {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1;
margin: 16px;
background: #fff;
}
.header, .content, .footer {
padding: 16px;
background: red;
}
<div class="row">
<div class="col">
<div class="header">Header #1</div>
<div class="content">Lorem Ipsum<br />Dolor<br />Sit Amet</div>
<div class="footer">Footer</div>
</div>
<div class="col">
<div class="header">Header #2</div>
<div class="content">Lorem Ipsum<br />Dolor</div>
</div>
</div>
Unfortunatly the second header isn't align vertically to the top. Is there a way to archive this with flexbox? I need the ".header" to be aligned the the top and the ".content" to be centered within the rest of the box.
Greetings!
No, not really, not without another wrapper which is a flex-container.
As flexbox is, to a certain extent based on manipulting margins, there is no method (AFAIK, although I'd be interested to find out if there is) to justify-content: center and then align-self a child element to somewhere else other than center.
I'd go with something like this: Add a wrapper to the "content" div, give it flex:1 to fill the remaining space below the header, then make that wrapper display:flex with justify-content:center.
This seems to be the most logical method
.col {
height: 150px;
width: 80%;
margin: 1em auto;
border: 1px solid grey;
display: flex;
flex-direction: column;
}
.header {
background: lightblue;
}
.content {
background: orange;
}
.flexy {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
background: plum;
}
<div class="col">
<div class="header">Header #2</div>
<div class="flexy">
<div class="content">Lorem Ipsum
<br />Dolor</div>
</div>
</div>
Codepen Demo
Flexbox opens up all sorts of opportunities with margin: auto; this is one of them. Setting margin to auto along the flex axis (vertical in this case) will absorb any extra space before dividing it up between the flex items. Finally it's possible to vertically center stuff without creating a div soup.
.row {
display: flex;
align-items: stretch;
margin: -16px;
background: #ddd;
}
.row .col {
display: flex;
flex-direction: column;
flex: 1;
margin: 16px;
background: #fff;
}
.header, .content, .footer {
padding: 16px;
background: red;
}
.content {
margin-top: auto;
margin-bottom: auto;
}
<div class="row">
<div class="col">
<div class="header">Header #1</div>
<div class="content">Lorem Ipsum<br />Dolor<br />Sit Amet</div>
<div class="footer">Footer</div>
</div>
<div class="col">
<div class="header">Header #2</div>
<div class="content">Lorem Ipsum<br />Dolor</div>
</div>
</div>

display: webkit-flex Pushes inline-block div to next line in Safari

I´m trying to learn HTML/CSS and find that when I add
display: -webkit-flex; to the CSS, the last div in the nav is pushed to the next line. When I disable flex box by simply deleting the line the div jumps back up to the (inline-block) nav. I'm currently testing in safari
The page looks as it should in Firefox, though not in Safari, any suggestions as to why?
Here's the code:
<body>
<header>
<div class="logo">
<h1>Guitar site</h1>
</div>
<nav>
<div class="leftMenu">
Home
</div>
<div class="centerMenu">
<div>
Beginner
</div>
<div>
Advanced
</div>
<div>
Tips
</div>
</div>
<div class="rightMenu">
Contact
</div>
</nav>
</header>
<h1> test</h1>
</body>
This is the all the CSS I've written, there is also a CSS reset section that I haven't included.
.leftMenu,
.rightMenu,
.centerMenu {
text-align: center;
display: inline-block;
border-bottom: solid .1em;
display: -webkit-flex;
}
.leftMenu,
.rightMenu {
background-color: #454ed6;
height: 2em;
padding-top: 1em;
width: 17.5%;
-webkit-justify-content: space-around;
}
.leftMenu {
float: left;
}
.rightMenu {
float: right;
}
.centerMenu a {
display: block;
height: 2em;
}
.centerMenu {
width: 65%;
height: 6em;
background-color: #86acbe;
-webkit-flex-direction: column;
-webkit-justify-content: space-around;
}
The main idea behind the flex layout is to give the container the ability to alter its items' width/height (and order) to best fill the available space.
So the main container in your case is nav element; and you have to define display:flex property for nav element. And your navigation HTML structure is not in proper format.
Check the Demo and here is your modified CSS Code.
nav{display: -webkit-flex;
display: -webkit-box; /*for older safari version*/
display: flex;}
.leftMenu,
.rightMenu,
.centerMenu {
text-align: center;
border-bottom: solid .1em;
justify-content: space-around;
/*display: inline-block;
display: -webkit-flex;*/
}
.leftMenu,
.rightMenu {
background-color: #fbfbfb;
height: 2em;
padding-top: 1em;
width: 17.5%;
/*-webkit-justify-content: space-around;*/
}
/*.leftMenu {
float: left;
}
.rightMenu {
float: right;
}*/
.centerMenu a {
display: block;
height: 2em;
}
.centerMenu {
width: 65%;
height: 6em;
background-color: #86acbe;
/* -webkit-flex-direction: column;
-webkit-justify-content: space-around;*/
}
<header>
<div class="logo">
<h1>Guitar site</h1>
</div>
<nav>
<div class="rightMenu">
Home
</div>
<div class="rightMenu">
Beginner
</div>
<div class="rightMenu">
Advanced
</div>
<div class="rightMenu">
Tips
</div>
<div class="rightMenu">
Contact
</div>
</nav>
</header>
<h1> test</h1>

Is there a way of doing this with flexbox?

My main <div> have a fixed height, but when I try to use box-orient: horizontal on it, they stay all above the first <div>, even with an overflow hack.
I'm stuck. This is what I need:
and this code:
<style>
.box {
outline: 1px solid red;
width: 1000px;
height: 450px;
overflow: hidden;
display: box;
box-pack: center;
box-align: center;
box-orient:vertical;
}
.boxitem {
width:150px;
height:200px;
background:#ccc;
}
</style>
<div class="box">
<div id="box1" class="boxitem">flexbox item 1</div>
<div id="box2" class="boxitem">flexbox item 2</div>
<div id="box3" class="boxitem">flexbox item 3</div>
</div>
You're using properties from the 2009 spec, which is being phased out in favor of this draft: http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/. You actually need box-orient: vertical from the 2009 spec, but that still won't help you because as far as I can tell, no one ever implemented box-lines: multiple to enable wrapping. You need the ability to wrap if you only want to use one flex container element.
So, the code below will cover all of your bases for browsers that supports the Flexbox spec in its entirety: Opera, Chrome, IE10.
http://jsfiddle.net/FwfDV/
.box {
outline: 1px solid red;
width: 1000px;
height: 450px;
display: -webkit-flexbox;
display: -ms-flexbox;
display: -webkit-flex;
-webkit-flex-flow: column wrap;
-ms-flex-flow: column wrap;
flex-flow: column wrap;
-webkit-flex-pack: justify; /* optional */
-ms-flex-pack: justify; /* optional */
-webkit-justify-content: space-between; /* optional */
justify-content: space-between; /* optional */
}
#supports (display: flex) and (flex-wrap: wrap) {
.box {
display: flex;
}
}
.boxitem {
width: 150px;
height: 200px;
background: #ccc;
}
<div class="box">
<div id="box1" class="boxitem">flexbox item 1</div>
<div id="box2" class="boxitem">flexbox item 2</div>
<div id="box3" class="boxitem">flexbox item 3</div>
<div id="box4" class="boxitem">flexbox item 4</div>
<div id="box5" class="boxitem">flexbox item 5</div>
<div id="box6" class="boxitem">flexbox item 6</div>
</div>
However, if your "boxitem" elements are regular/fixed sizes like this, I recommend using CSS Columns instead, which has a bit wider support and can do nearly the same job.

Resources