In this example we’ll use relative positioning to set up the header. We start with this:
With relative positioning, elements are still in the normal document flow, but they don’t influence the layout of the surrounding elements. This is because the positional offsets we provide position it relative to its original position. We’ll start by setting the logo and nav to position:relative and give the logo a width.
Now, if we were to style the logo bottom:20px;, it would offset it 20px up from the bottom from its original position.
If we were to do right:20px;, it would move to the left, and it we were to do left:20px; it would move to the right. Notice also how the nav elements are not affected or moved by the logo.
Next, we’ll reposition our main nav so in it’s inline with our logo. To move it up, we’ll give it a bottom: 32px; and to move it to the right, we’ll give it a left: 200px;.
Now, because the header and nav are block level elements, They’re both still taking up an entire line or block on the page. And since they’re still in the normal document flow, the positioning offsets we defined are causing the logo and nav to overflow its parent header container, causing the big gap on the right.
The best way to fix this is by giving the header an overflow value of hidden.
Relative positioning also serves as a positioning context for absolute positioning, because an element with absolute positioning will always be relative to its first parent that has a relative position. If no parent element has that, the browser viewport will be the positioning context.
We’re going to use absolute positioning to style this header. Here’s what we’re starting with:
First, we need to establish the header container as position:relative. Then we’ll set the logo and nav elements as position:absolute;
As you can see, this positions them in the top left part of the container header div by default. The space we’re seeing is the padding applied to the header container (not the logo), and the margins given to the list items. However, if we were to select the logo and set its top and left offsets to 0…
The key thing here is 0 will put it at that edge of its parent container, and a positive value will move it away from it.
So, when absolute positioning is used, the element is completely removed from the normal document flow, so it no longer affects the positioning of other elements (like the nav items).
You can use negative values as well, which can move elements outside of their parents.
We’ll use offsets now to position the elements.
Now, let’s say we wanted to put the nav items on the right.
Unfortunately there’s no clearfix for this like there is for floats, so you’ll need to make sure there’s always a height for the container.
Next, we’ll want to reposition the three columns of content using absolute positioning.
Now, we’ll give the columns positioning offsets. Give the .primary-content a new width and position it 30% from the left, and the .secondary one right on the right.
Once again, because we’re using absolute positioning, we need to set the height of the parent containers to 100%, or the content-row will collapse, which is why the footer is jammed up in there. For some reason I had to do it for .main-wrapper and .col as well, so I guess it’s for all containing parents.
We can also now add more content above and below, and also remove the wrapper styling without breaking the layout.
Best example of this is with a fixed header. Once again, we’re starting with this:
First, we’ll give the main-header container a width:100% and position:fixed; Because we’ve given it that position, we can now use the top, bottom, left and right offsets we’ve used before, so we’ll also give it a top:0; to make sure it stays at the top.
The second screen shows an issue – since the columns are positioned absolute, they have a higher z-index than the header which has position:fixed;. To fix this, give it a z-index of anything higher than 1, since we haven’t specified one for the columns. Though you wouldn’t normally set up the columns with absolute positioning, it’s good to keep z-index in mind.
If we wanted the header to be at the bottom of the page, you’d simply change it to bottom:0;
When the header is position:fixed, it’s also being taken out of the normal document flow, as you can see in the example below. It’s not affecting/pushing down the position of the banner like it would in the normal document flow, and is instead covering it.
To fix this, add some top padding to the body of the page. Since the header is 100px tall, we’ll use 100px.
There’s a quick and easy way to center absolutely positioned elements inside their parent container. We’re going to make an icon with a pseudo element then center it vertically and horizontally.
We’ll then set up a pseudo element. Content will be blank, display will be block, and we’ll set the width and height we want. Then, we’ll use background to set the background image url, and set background-size:100%, which means it will use the width and height we just specified. Then, we’ll set it’s position to absolute.
Now w’ll give it some offsets to center it. If we set all four ones to 0, and set the margins to auto, it will position it right in the center.
Still tough to decide whether to use today. It’s awesome, but the browser support for it is very weak for older browsers. Flexbox is source order independent, so you can layout elements in any direction/order regardless of where they’re written in the markup.
Building a navigation with flexbox
Starting with this:
Notice how the header logo has been added as a list item to the main nav. This will make it easier for us later.
First, we need to establish a flex formatting context. We do this with display:flex; By doing so on the .main-nav, we make the list items inside it flex items, which by default lays everything out in a row, in what’s called the flex direction. This let’s us layout the list items in all sorts of different ways.
For perfectly vertically aligned elements, we can set the li’s to align-self:center;. We also need to set a height for its parent container.
Next we’ll give them some margin left and right.
Now, with flexbox, margins can have a pretty significant effect on flex items. Let’s say that we wanted to put the nav items on the right hand side and keep the logo on the left. We’ll use .main-logo:first-child because it’s more specific than the .main-nav li descendent selector above. When we set margin-right to auto, it absorbs all the extra space and pushes the remaining list items to the right.
For now, we’ll keep it at 50px.
We can use the flex-grow property to control the amount of space the flex items take up in the main nav. If we want all the links to be evenly spaced, we can do flex-grow:1;. The value 1 represents the ratio of free space we want them to take up.
If we want the logo to be bigger, simply give it a larger flex-grow value of 2, which makes it take up twice as much space of a flex item with the value 1.
For this to work in Safari, we must copy the flex declarations and use the -webkit- prefix.
IE10 uses a whole different syntax, which thankfully we won’t be going into today.
In this example, he’s added data icons to each nav link, whose values are html unicode characters. He’s using a before psuedo element to insert the content based on the value of the data-icon attribute set.
Next, we’ll position them with a left:-30%;, and add an overflow:hidden to the nav links, to hide them.
We’ll add a transition to make it look nicer.
Now, we’ll make the flex items grow on hover. We’ll select li items when hovered that are not the .main-logo (cause we don’t want that to expand), and give them a new flex-grow. Then, we’ll select main-nav list items and give them a transition to make it smoother.
Now we’ll layout the three columns with flexbox. Starting with this:
First we’ll create that flex formatting context in the containing .content-row element. This makes the child elements act as flex items, which puts them in a row, and the stretch to fill the container both horizontally and vertically.
To have the columns be evenly distributed, we can give them a flex value of 1.
Now, let’s say we want primary-content column to take up twice the amount of space. Simply select it and give it a flex value of 2.
Once again, we can change the order of the columns without changing the markup. If we want primary content to be first, we can use the order property.
To swap the extra and secondary content ones, select the extra content and give it an order of 1.
Lastly, once again we need to include the vendor prefixes so it works in Safari.
Providing fallbacks with Modernizr
This will allow us to provide fallbacks for browsers that don’t support Flexbox. It detects if a feature is supported by a browser, and if it doesn’t, it falls back to conditional CSS we write in the stylesheet. It lets you select which features you want to detect for. Then you download the js file and simply link it in the head section like any other one.
To do this, we’ll find where we put our flexbox styles and adjust them. For display: flex in .main-nav, this is fine because if a browser doesn’t support it it will go back to the default display value, in this case block. We need a fallback for the list items. So, we select the class .no-flexbox, then any list items in the class .main-nav inside of that.
Next, we’ll fix the columns.
Lastly, we’ll fix the icons by adjusting their position when you hover.