I have a side nav-bar. I want the items to be evenly spaced so that it fills out the whole 'bar'.
I've tried making my 'container' have justify-content: space-between. However, it's not taking the flex attribute.
I'll post my code as it'll show what I mean.
I also would like it that it stays 'fixed' but doing so cuts the 'container' to about 50% height.
https://codepen.io/azhorabai/pen/MOOwrJ
* {
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
font-family: "Dosis", sans-serif;
}
body {
display: flex;
min-height: 100vh;
flex-flow: row wrap;
margin: auto;
background-color: black;
}
.side-menu {
background-color: lightcoral;
font-size: 2em;
text-transform: uppercase;
justify-content: space-between;
}
.side-menu ol {
list-style-type: none;
max-width: 100%;
padding: 0px 30px;
}
.side-menu li {
line-height: 5em;
}
#projects {}
.top-header {
background-color: lightgreen;
height: 20vh;
box-sizing: border-box;
}
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Dosis:400,700" rel="stylesheet">
</head>
<body>
<title>X. Quisite</title>
<nav class="side-menu">
<ol>
<li class="about-me">About</li>
<li class="projects">Projects
<li>
<li class="skills">Services</li>
<li class="contact">Contact</li>
</ol>
</nav>
</body>
</html>
The justify-content property applies only to flex containers. So it must apply to an element that also has display: flex or display: inline-flex (read more).
body {
display: flex;
height: 100vh;
margin: 0;
background-color: black;
}
.side-menu {
background-color: lightcoral;
font-size: 2em;
text-transform: uppercase;
justify-content: space-between;
display: flex; /* new */
flex-direction: column; /* new */
}
a {
padding: 0px 30px;
}
<nav class="side-menu">
<a class="about-me">About</a>
<a class="projects">Projects</a>
<a class="skills">Services</a>
<a class="contact">Contact</a>
</nav>
When applying flex rules like justify-content: space-between; you need to apply them to an element with the rule display: flex declared.
These flex rules will apply to direct descendant nested elements only, so you should declare them to the unordered list item (ol), then specify the flex-direction: column so that you can justify the content vertically. In addition, you can declare align-items: center; to horizontally align the list items (these rules typically work in reverse if the direction has been specified horizontal, or row, e.g: flex-direction: row).
Lastly, your fixed navigation will occupy the full height of the viewport if you declare top: 0 and bottom: 0 properties.
*{
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
font-family: 'Dosis', sans-serif;
}
body{
display: flex;
min-height: 100vh;
flex-flow: row wrap;
margin: auto;
background-color: black;
}
.side-menu {
background-color: lightcoral;
font-size: 2em;
text-transform: uppercase;
position: fixed;
top: 0;
bottom: 0;
}
.side-menu ol {
list-style-type: none;
max-width: 100%;
padding: 0px 30px;
display: flex;
flex-direction: column;
justify-content: space-around;
margin: 0;
height: 100%;
align-items: center;
}
.side-menu li{
/*line-height: 5em;*/ /* unset for code snippet preview */
}
#projects{
}
.top-header{
background-color: lightgreen;
height: 20vh;
box-sizing: border-box;
}
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Dosis:400,700" rel="stylesheet">
</head>
<body>
<title>X. Quisite</title>
<nav class="side-menu">
<ol>
<li class="about-me">About</li>
<li class="projects">Projects</li>
<li class="skills">Services</li>
<li class="contact">Contact</li>
</ol>
</nav>
</body>
</html>
Related
I have a navigation bar and I added a red line on the bottom when hovering any item of the list, but I want to move that red line under the header (something like "Services"), any idea how to achieve this?
I added an small sample in codepen so you can easily check the HTML and CSS code
header {
background-color: lightblue;
padding-top: 1rem;
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
header li:hover {
height: 100%;
border-bottom: 2px solid red;
}
<header>
<a href="/">
<p>Whatever logo</p>
</a>
<nav>
<ul>
<li>About us</li>
<li>Services</li>
<li>Pricing</li>
<li>Blog</li>
</ul>
</nav>
CONTACT
</header>
Link to check the code
You can fix the header height and also fix the height of navbar items.
Also, you had one issue where on hover li elements are moving. You can also fix that with always adding border with transparent color to the element, so the overall height of the element won't change on hover state.
Here is the fixed CSS
header {
background-color: lightblue;
position: sticky;
display: flex;
height: 60px;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
height: 60px;
}
header li {
display: flex;
align-items: center;
border-bottom: 2px solid transparent;
height: 60px;
}
header li:hover {
border-bottom: 2px solid red;
}
https://codepen.io/swarajgk/pen/JjZewPo?editors=1100
I think just giving height to all list elements the same as the header will work.
Like this:-
header {
background-color: lightblue;
padding-top: 1rem;
height: 3rem;
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
height : 100%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
header li{
height: inherit;
}
header li:hover {
border-bottom: 2px solid red;
}
<body>
<header>
<a href="/"
><p>Whatever logo</p></a>
<nav>
<ul>
<li>About us</li>
<li>Services</li>
<li>Pricing</li>
<li>Blog</li>
</ul>
</nav>
CONTACT
</header>
</body>
Hope this solves the issue.
header {
background-color: lightblue;
padding-top: 1rem;
height: 3rem;
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
height : 100%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
header li{
height: inherit;
}
header li:hover {
border-bottom: 2px solid red;
}
I'd suggest the following approach, with explanatory comments in the CSS:
/* removing default padding and margin from all
elements, and forcing the browser to use the
same sizing algorithm - border-box - to calculate
element sizes, including the padding and border
widths in the declared size: */
*, ::before, ::after {
box-sizing: border-box;
padding: 0;
margin: 0;
}
/* setting common properties for the two element
groups: */
header,
header nav ul {
/* using display: flex layout: */
display: flex;
/* forcing the flex-items within the flex parent
to take the full height of that parent: */
align-items: stretch;
}
header {
background-color: lightblue;
block-size: 3em;
position: sticky;
justify-content: space-around;
}
/* using :is() to combine the two selectors
header a,
header li
into one selector: */
header :is(a, li) {
/* using grid layout: */
display: grid;
/* positioning the - including text - content
at the center of the element: */
place-items: center;
}
header nav {
min-width: 50%;
}
header nav ul {
/* the <ul> isn't a flex-item so we have to specify
that we want it to take all available space on
the block-axis (equivalent to 'height' in left-to-right
languages such as English): */
block-size: 100%;
list-style: none;
justify-content: space-between;
}
header li {
/* to prevent the jumping content: */
border-bottom: 2px solid transparent;
}
header li:hover {
/* to style the color of the bottom border: */
border-bottom-color: red;
}
<header>
<a href="/">
<p>Whatever logo</p>
</a>
<nav>
<ul>
<li>About us</li>
<li>Services</li>
<li>Pricing</li>
<li>Blog</li>
</ul>
</nav>
CONTACT
</header>
JS Fiddle demo.
References:
align-items.
display.
justify-content.
place-items.
Bibliography:
"Aligning items in a flex container," MDN.
"Basic concepts of flexbox," MDN.
"Box alignment in grid layout," MDN.
This question already has answers here:
Center one and right/left align other flexbox element
(11 answers)
Closed 4 years ago.
I'm trying to create a footer using CSS flex, with the following conditions :
3 elements (links)
the first 2 must be at the left of the screen
the last one must be perfectly centered
Live snippet
* {
box-sizing: border-box;
text-decoration: none;
}
html, body {
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
width: 100%;
height: 100%;
display: flex;
flex: 1;
}
footer {
background: black;
}
a {
color: inherit;
}
ul {
margin: 0;
display: flex;
height: 66px;
list-style: none;
align-items: center;
justify-content: center;
}
li {
flex: 1;
color: white;
height: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
}
li div {
padding: 1em;
}
li.centered {
justify-content: center;
}
li.centered div {
background: lightgrey;
color: black;
height: 100%;
padding: 1em;
display: flex;
align-items: center;
justify-content: center;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
</head>
<body>
<main></main>
<footer>
<ul>
<li>
<div>
First
</div>
<div>
Second, large, full of text element
</div>
</li>
<li class="centered">
<div>
Centered element
</div>
</li>
<li></li>
</ul>
</footer>
</body>
</html>
This is working fine, but I dislike the last empty li element (use to add a 3rd columns).
Does anyone have a solution for this, without an empty element in dom ?
This is working fine, but I dislike the last empty li element (use to add a 3rd columns).
Does anyone have a solution for this, without an empty element in dom ?
You can easily replace it with a pseudo element (ul:after) - you just need to make sure that you apply the style you have for li for that one as well then.
* {
box-sizing: border-box;
text-decoration: none;
}
html, body {
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
footer {
background: black;
}
a {
color: inherit;
}
ul {
margin: 0;
display: flex;
height: 66px;
list-style: none;
align-items: center;
justify-content: center;
}
/* pseudo element to replace empty LI at the end */
ul:after {
content: ""; /* content property needs to be set, otherwise pseudo element is not rendered at all */
}
/* apply general LI formatting for pseudo element as well */
li, ul:after {
flex: 1;
color: white;
height: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
}
li div {
padding: 1em;
}
li.centered {
justify-content: center;
}
li.centered div {
background: lightgrey;
color: black;
height: 100%;
padding: 1em;
display: flex;
align-items: center;
justify-content: center;
}
<footer>
<ul>
<li>
<div>
First
</div>
<div>
Second, large, full of text element
</div>
</li>
<li class="centered">
<div>
Centered element
</div>
</li>
</ul>
</footer>
You can achieve that by using:
li.centered div {
position: relative;
left: 0;
right: 0;
transform: translateX(-50%);
}
I am aware that is not the most modern solution and I didn't use the flexbox but you don't need to create empty elements in this way.
I want to build a navigation in the header containing three items where the first two ones are aligned left and the third one is aligned right. Tried it by use of flexbox but there is an arror: The ul is exceeding the width of it's parent container.
header {
width: 100%;
background: #417690;
margin-left: 10px;
margin-right: 10px;
font-size: 20px;
height: 70px;
}
header ul {
height: 100%;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
/* justify-content: center; */
}
header ul li {
display: inline-block;
padding-right: 15px;
margin-left: 10px;
}
.filler {
flex-grow: 1;
}
<header>
<ul>
<li>Logo</li>
<li>New article</li>
<li class="filler"></li>
<li>username</li>
</ul>
</header>
How can I fix this?
Tested in FF and Opera.
Reset margin to zero and add box-sizing: border-box to all elements to include the padding in the size calculations. You may also reset the padding for the ul element - see demo below:
* { /* ADDED */
box-sizing: border-box;
}
header {
width: 100%;
background: #417690;
/*margin-left: 10px;
margin-right: 10px;*/
font-size: 20px;
height: 70px;
}
header ul {
height: 100%;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
/* justify-content: center; */
padding: 0; /* ADDED */
}
header ul li {
display: inline-block;
padding-right: 15px;
margin-left: 10px;
}
.filler {
flex-grow: 1;
}
<header>
<ul>
<li>Logo</li>
<li>New article</li>
<li class="filler"></li>
<li>username</li>
</ul>
</header>
Try this:
header ul {
box-sizing: border-box;
padding: 0;
}
I am styling a header of a webpage. I want the header to be a single line which includes a logo and some navigational links. I feel the best, most modern way to layout this header today is with CSS3's flexbox, so that is what I would like to use.
I would like for the logo to be as far left in the flex container as possible, and the remaining navigation items to be as far right as possible. This could easily be achieved by floating the elements left and right, but that is not what I would like to do. So...
How do you align child elements of a flexbox container to opposite far ends of the main axis?
There is a property for the flexbox child elements that allows you to do this on the cross axis, align-self, but it seems there is none to do this on the main axis.
The best way I have come up with to achieve this is to insert an additional, empty, element in between the logo and the navigational links to serve as a spacer. But part of the reason I am choosing to use flexbox for this header is to cohere with a responsive design and I do not know of a way to make the spacing element take up all the remaining space, regardless of the width of the viewing window.
Here is where I currently stand with the mark-up, simplified to only include the elements pertinent to this situation.
HTML
<ul>
<!-- Should be as far left as possible -->
<li id="main">Some Logo <span>Some tag line.</span></li>
<!-- Should be as far right as possible -->
<li>Home</li>
<li>Products</li>
<li>Price Sheet</li>
<li>Capabilities</li>
<li>Contact</li>
</ul>
CSS
ul {
width: 100%;
display: flex;
flex-flow: row nowrap;
justify-content: flex-end;
align-items: center;
padding: 0;
margin: 0;
list-style: none;
}
li {
margin: 0 8px;
padding: 8px;
font-size: 1rem;
text-align: center;
font-weight: bold;
color: white;
background: green;
border: solid 4px #333;
}
#main { font-size: 2rem; }
#main span { font-size: 1rem; }
From your question:
I do not know of a way to make the spacing element take up all the remaining space, regardless of the width of the viewing window.
This is exactly what the flex-grow CSS rule was designed for. If only one child element has the flex-grow attribute set, then it will take up all the remaining space in the flex container. The only markup you will need in this case is the following:
HTML:
<li id="spacer"></li>
CSS:
#spacer {
visibility: hidden;
flex-grow: 1;
}
Full Live Demo:
ul {
width: 100%;
display: flex;
flex-flow: row nowrap;
justify-content: flex-end;
align-items: center;
padding: 0;
margin: 0;
list-style: none;
}
li {
margin: 0 8px;
padding: 8px;
font-size: 1rem;
text-align: center;
font-weight: bold;
color: white;
background: green;
border: solid 4px #333;
}
#main { font-size: 2rem; }
#main span { font-size: 1rem; }
#spacer {
visibility: hidden;
flex-grow: 1;
}
<ul>
<!-- Should be as far left as possible -->
<li id="main">Some Logo <span>Some tag line.</span></li>
<!-- Spacer element -->
<li id="spacer"></li>
<!-- Should be as far right as possible -->
<li>Home</li>
<li>Products</li>
<li>Price Sheet</li>
<li>Capabilities</li>
<li>Contact</li>
</ul>
JSFiddle Version: https://jsfiddle.net/7oaahkk1/
I think the only flexibility that is needed, at least on large screens, should go on the first flex-item in the list. The one you want to place your logo at.
By setting this items flex-grow rule to 1 and the text-align to left it will stay on the left side, growing in size, making sure all other items stay on the right side. Since the logo may have a greater height value than all the other items it would make sense to change the align-items rule to baseline, making sure all items are horizontally aligned.
Furthermore i have added a few media queries to change the flex settings accordingly.
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: border-box;
}
body {
margin: 0;
}
ul {
width: 100%;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: stretch;
padding: 0;
margin: 0;
list-style: none;
}
li {
margin: 0;
padding: 8px;
font-size: 1rem;
text-align: center;
font-weight: bold;
color: white;
background: green;
border: solid 4px #333;
}
li:first-child {
font-family: sans;
font-size: 2em;
text-align: center;
}
li:first-child span {
font-size: initial;
}
#media (min-width: 34em) {
ul {
flex-flow: row wrap;
justify-content: space-between;
align-items: flex-start;
}
li {
flex: 1;
}
#main {
flex: 0 0 100vw;
}
}
#media (min-width: 48em) {
ul {
justify-content: flex-end;
align-items: baseline;
}
li {
flex: none;
}
#main {
flex: 1 0 auto;
text-align: left;
}
}
<ul>
<!-- Should be as far left as possible -->
<li id="main">Some Logo <span>Some tag line.</span></li>
<!-- Should be as far right as possible -->
<li>Home</li>
<li>Products</li>
<li>Price Sheet</li>
<li>Capabilities</li>
<li>Contact</li>
</ul>
Essentially you need a row container with two child columns
container is a flexible div
column one is a flexed div with the logo
column two is a flexible ul with flexed li's
AND 'justify-content: space-between' to move the columns to the far ends
Check my snippet (full page)!
.container,
.menu {
display: flex;
}
.container {
justify-content: space-between;
width: 100%;
}
.menu {
padding: 0;
margin: 0;
list-style: none;
}
li,
.logo {
margin: 0 8px;
padding: 8px;
font-size: 1rem;
text-align: center;
font-weight: bold;
color: white;
background: green;
border: solid 4px #333;
}
#main {
font-size: 2rem;
}
#main span {
font-size: 1rem;
}
<div class="container">
<div id="main" class="logo">Some Logo <span>Some tag line.</span>
</div>
<ul class="menu">
<li>Home</li>
<li>Products</li>
<li>Price Sheet</li>
<li>Capabilities</li>
<li>Contact</li>
</ul>
</div>
JSfiddle Demo
Wrap a ul over the rest of the list items and use nested flex container. This is to provide flexbox to act on two elements.
Use justify-content: space-between on the main flexbox parent to equally space the two elements.
.parent-menu {
width: 100%;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
/* Modify */
align-items: center;
padding: 0;
margin: 0;
list-style: none;
}
li {
margin: 0 8px;
padding: 8px;
font-size: 1rem;
text-align: center;
font-weight: bold;
color: white;
background: green;
border: solid 4px #333;
}
#main {
font-size: 2rem;
}
#main span {
font-size: 1rem;
}
.right-menu {
display: flex;
/* Add */
}
<ul class="parent-menu">
<!-- Should be as far left as possible -->
<li id="main">Some Logo <span>Some tag line.</span>
</li>
<ul class="right-menu">
<!-- Should be as far right as possible -->
<li>Home</li>
<li>Products</li>
<li>Price Sheet</li>
<li>Capabilities</li>
<li>Contact</li>
</ul>
</ul>
One posibility is to set a right margin on the first element
ul {
width: 100%;
display: flex;
flex-flow: row nowrap;
justify-content: flex-end;
align-items: center;
padding: 0;
margin: 0;
list-style: none;
}
li {
margin: 0 8px;
padding: 8px;
font-size: 1rem;
text-align: center;
font-weight: bold;
color: white;
background: green;
border: solid 4px #333;
}
#main {
font-size: 2rem;
margin-right: auto; /* create a right margin as needed */
}
#main span { font-size: 1rem; }
#spacer {
visibility: hidden;
flex-grow: 1;
}
<ul>
<!-- Should be as far left as possible -->
<li id="main">Some Logo <span>Some tag line.</span></li>
<!-- Should be as far right as possible -->
<li>Home</li>
<li>Products</li>
<li>Price Sheet</li>
<li>Capabilities</li>
<li>Contact</li>
</ul>
I am trying to vertically position the "Distance" and "Duration" text in the center of their respective divs using flexbox, I can't seem to get it to work. I will also apply this to the "Calories" and "Share" text aswell.
I am also want to use flexbox to evenly space my 4x links vertaically in the middle column.
Codepen demo
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Runna - Track your run!</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
<link rel="stylesheet" type="text/css" href="css/reset.css">
<link rel="stylesheet" type="text/css" href="css/style.css">
<link href='http://fonts.googleapis.com/css?family=Lato:400,700,900' rel='stylesheet' type='text/css'>
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="js/js.js"></script>
</head>
<body>
<div id="main-wrapper">
<div id="head-bar">
<img class="logo" src="imgs/logo-blue.png">
</div>
<div id="map-container">
<iframe src="https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d11564.804405086046!2d172.59430635!3d-43.56069255!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e0!3m2!1sen!2snz!4v1418977732755" width="100%" height="100%" frameborder="0" style="border:0"></iframe>
</div>
<div id="control-container">
<div class="left-col">
<div class="distance-wrapper">
<div class="distance-title bold-title">DISTANCE:</div>
<div class="distance-figure">1.7KM</div>
</div>
<div class="duration-wrapper">
<div class="duration-title bold-title">DURATION</div>
<div class="duration-figure">10.42MINS</div>
</div>
</div> <!-- End of left col -->
<div class="middle-col">
<ul>
<li class="arrow"><i class="fa fa-chevron-down"></i></li>
<li>START</li>
<li>STOP</li>
<li>PAUSE</li>
</ul>
</div>
<div class="right-col">
<div class="calorie-wrapper">
<div class="calories bold-title">CALORIES</div>
<div class="calories-result">100 cal's</div>
</div>
<div class="share-wrapper">
<div class="share bold-title">SHARE</div>
<div class="share-icons">FB or Twitter</div>
</div>
</div> <!-- End of right col -->
</div>
</div>
</body>
</html>
CSS:
html {
box-sizing: border-box;
height: 100%;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
height: 100%;
font-family: 'Lato', sans-serif;
}
#main-wrapper {
height: 100vh;
}
#media all and (max-width: 40em) {
#head-bar {
background: black;
width: 100%;
height: 5vh;
}
.logo {
display: block;
margin: 0 auto;
height: 85%;
}
#map-container {
background: yellow;
height: 65vh;
width: 100%;
}
}
/***Control columns***/
#control-container {
width: 100%;
height: 30vh;
color: white;
font-family: 'Lato', sans-serif;
text-align: center;
background: #1b1b1b;
position: relative;
}
.left-col {
display: flex;
flex-direction: column;
width: 33.3%;
height: 100%;
/*height: 60px;*/
float: left;
}
.middle-col {
background: #151515;
width: 33.3%;
height: 100%;
float: left;
/*box-shadow: 0 0 8px 2px #000;*/
}
.right-col {
width: 33.3%;
float: left;
}
.distance-wrapper, .duration-wrapper {
flex: 1;
/*background: #ddd;*/
border-bottom: 1px solid yellow;
justify-content: center;
}
.calorie-wrapper, .share-wrapper {
display: block;
width: 100%;
}
.bold-title {
font-weight: 900;
font-family: 'Lato', sans-serif;
}
/***Middle Navigation***/
.middle-col {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.middle-col ul {
margin: 0;
padding: 0;
display: table;
width: 100%;
}
.middle-col li {
list-style-type: none;
}
.middle-col a {
color: white;
text-decoration: none;
display: block;
padding: 20px;
}
.middle-col a:hover {
background: green;
display: block;
}
#control-container:after {
content: "";
display: block;
height: 0;
clear: both;
}
I created this example with a smaller amount of HTML and, hopefully, greater semantic meaning.
Let's make this:
The HTML
The <section> element for the flex container
The <nav> element is a good container for the actions.
The description list element — <dl> — is a good wrapper for the stats. They have two children:
The Description Term element — <dt> — is used for the stat headings
The Description element — <dd> — is used for the stat value
<section class="control-container">
<dl class="distance">
<dt>Distance</dt>
<dd>1.7KM</dd>
</dl>
<dl class="duration">
<dt>Duration</dt>
<dd>10.42 Mins</dd>
</dl>
<dl class="calories">
<dt>Calories</dt>
<dd>100</dd>
</dl>
<nav class="actions">
Down
Start
Stop
Pause
</nav>
<div class="share">
<h2>Share</h2>
Facebook
Twitter
</div>
</section>
The Flex
The flex <section> container has display: flex and flex-flow: column wrap so its children will layout in columns and wrap when pushed outside.
The flex items are also given display: flex, flex-flow: column wrap and justify-content: center; so that the text is vertically centered. The nav is given flex-direction: row so that its links can be evenly centered vertically with align-items: center
The 4 sections which take up half of the height are given flex: 1 1 50%; they will each get half of a column height
The navigation is given flex: 1 1 100% so it will take up an entire column on its own
.control-container {
display: flex;
flex-flow: column wrap;
}
.control-container > * {
display: flex;
flex-flow: column wrap;
justify-content: center;
flex: 1 1 50%;
width: 33.33%;
text-align: center;
}
.control-container > nav {
flex-direction: row;
align-items: center;
flex: 1 1 100%;
}
.control-container > nav a {
flex: 1 1 100%;
}
Complete Example
* {
margin: 0;
padding: 0;
font: 100% arial;
}
.control-container {
display: flex;
flex-flow: column wrap;
height: 40vh;
min-height: 250px;
min-width: 300px;
margin: 0 auto;
}
.control-container > * { /* target all direct children */
display: flex;
flex-flow: column wrap;
justify-content: center;
flex: 1 1 50%;
width: 33.33%;
text-align: center;
background: #333;
color: #FFF;
}
.control-container > nav {
flex-direction: row; /* allows vertical centering with align-items: center; */
align-items: center;
flex: 1 1 100%; /* take up entire column */
background: #000;
}
.control-container > nav a {
flex: 1 1 100%; /* 100% pushes each link so they wrap */
}
/*Change the order of the flex items so the stats can be kept together in the HTML*/
.distance,
.duration,
.actions {
order: 1;
}
.calories {
order: 3;
}
.share {
order: 4;
}
.wrapper {
max-width: 1200px;
margin: 0 auto;
}
.control-container dt,
.control-container h2 {
font-weight: bold;
}
.share h2 {
margin-top: calc(1em + 15px); /*push "share" down so it aligns with "duration" 1em accounts for the extra line of text */
}
.control-container a {
color: #FFF;
text-decoration: none;
}
dt,
dd,
.share * {
padding: 5px;
}
iframe {
width: 100%;
height: calc(60vh - 104px);
/* viewport height minus flex container height and header height ( + there is a stray 4px somewhere)*/
min-height: 300px;
}
header {
height: 100px;
text-align: center;
background: #000;
}
<div class="wrapper">
<header>
<img src="http://www.placehold.it/100" />
</header>
<iframe src="https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d11564.804405086046!2d172.59430635!3d-43.56069255!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e0!3m2!1sen!2snz!4v1418977732755" frameborder="0" style="border:0"></iframe>
<section class="control-container">
<dl class="distance">
<dt>Distance</dt>
<dd>1.7KM</dd>
</dl>
<dl class="duration">
<dt>Duration</dt>
<dd>10.42 Mins</dd>
</dl>
<dl class="calories">
<dt>Calories</dt>
<dd>100</dd>
</dl>
<nav class="actions">
Down
Start
Stop
Pause
</nav>
<div class="share">
<h2>Share</h2>
Facebook
Twitter
</div>
</section>
</div>
So i ended up working it out, I didnt realise you can add the display: flex and flex-direction: column; etc properties again if you have already added them to the main container. Anyway I added the following code to my wrappers and it works:
.distance-wrapper, .duration-wrapper {
flex: 1;
border-bottom: 1px solid yellow;
display: flex; // Important
flex-direction: column; // Important
align-items: center;// Important
justify-content: center; // Important
}