Positioning Schemes
Relative Positioning
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 change it to top:20px;, it would move it 20px from the top.
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.
Absolute positioning
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.
The downside to the absolute positioning is that we’ll need to make sure there’s a height in the containing element, otherwise it will collapse. For example:
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.
Like before, we need to set the containing element (.content-row) to position:relative;. Then, we’ll set widths for the columns and position them absolute.
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.
Fixed Positioning
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.
Absolute Centering
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.
First, we’ll need to set a relative positioning context for the icon, so that any child or pseudo element will be relative to its width and height.
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.
Flexbox Layout
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.
Animating Flexbox
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.
They’re currently positioned absolute, to get them inside the nav links, we’ll give the links a relative positioning context. The logos will then be position 10px from the top of the nav link area.
Next, we’ll position them with a left:-30%;, and add an overflow:hidden to the nav links, to hide them.
Now, we’ll make it so that when you hover the icons appear. We’ll select the a under .main-nav, when you hover it selects the pseudo element and moves it over 10% from the left.
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.
The transition also works on mobile devices.
Flexbox Columns
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.
You’ll know it’s working when you see class=” js flexbox” the html element when viewing the page source. This means that javascript is enabled in the browser, and that it supports flexbox. If it didn’t, it would display no-flexbox, which we can use to provide fallback styles for browsers that don’t support it.
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.