New terms from treehouse – CSS Layout Techniques Part 3 – Grid Layout

Grid Layout

Understanding Grids A grid allows us to lay out our design elements and content in a simple yet versatile way, because all of the alignment, positioning, floating, even the clearfix, is already built into the grid system. And it’s usually responsive, so it’s able to adapt to any device or viewport size. The layout should be thought of as a set of rows and columns. Rows are what contain the columns and keep the grid in place. Columns keep things nicely aligned to the grid. Screen Shot 2014-06-30 at 2.34.53 PM The grid itself is determined by some css like margins, widths, etc that you write ahead of time. First, we’ll determine the max number of columns we want in the grid, in this case 12. We need fixed pixel widths to determine how wide each of those should be, in this case 65px. Keep in mind that columns can span the width of multiple columns as long as they don’t exceed the max number of columns in the row. Screen Shot 2014-06-30 at 2.38.21 PM Columns also have margins aka gutters that separate them from adjacent columns. We’ll give all but the first column in our grid a 20px left margin.


Creating Fluid Grid Columns We want to use percentages for setting up the columns rather than fixed lengths, so that it can respond based on the viewport size. If you add up 12 columns at 65px each, and 11 20px left margin gutters (because the first one doesn’t have one), that gives you a total of 1000px, and we can do some math to figure out the percentage. Our first target column width is the first column that doesn’t have the left margin gutter, and is 65px, divided by our context of 1000px, gives us .065. To make that a percentage, move the decimal over by two, giving us 6.5%. Then, we’ll do how much width two columns would be, which includes the gutter between them as well, which is 65 + 65 + 20 = 150 /1000 =  .150 x 100 =  15%. Lastly, we’ll do one for the width of three columns. 65 + 65 + 65 + 20 + 20 = 235px /1000 = .235 x 100 = 23.5%. You would then go through and do this for all of them, up to twelve which is the highest number we want. Screen Shot 2014-06-30 at 2.52.26 PM Notice .grid-12 is our max-width, which spans across the whole grid. Now anytime we want a column to span a certain number of columns, we can give it the appropriate class.


Creating the Grid Container Next we’ll create a new class .grid-container and give it some padding and margin to center it. Screen Shot 2014-06-30 at 2.59.02 PM Then we need to set up the styles that will layout the columns in the grid container. We use a child selector for child elements of .gird-container with a class that starts with “grid-“, so any of the ones we created early. We’ll give them a float:left;, and since we’re using floats, a min-height to prevent them from horizontally collapsing. We’ll add some padding, then some margin. Earlier, it was decided that the left margin would be 20px, and to make that a percentage we divide by the total width 1000px, which gives us .020, then x 100 to give us 2%. Screen Shot 2014-06-30 at 2.59.02 PM Now, we don’t want the first column to have a margin-left, so we’ll set the margin of the first column to 0. We’ll select it using a :first-child pseudo-class. Screen Shot 2014-06-30 at 3.05.57 PM Lastly, we’ll make it so the last column always floats right, so it’s always flush with the right side of the page. Screen Shot 2014-06-30 at 3.06.34 PM Now, we’ll need to do a clearfix to clear our floats, so the grid container won’t collapse. So, we’ll add it with an :after pseudo-element to build it into our grid. Screen Shot 2014-06-30 at 3.10.04 PM


Testing Our Grid Now that all that’s set up, we can plug in some of these grid classes. We’re starting with this: Screen Shot 2014-06-30 at 3.13.11 PM First, we’ll use them in our header. We’ll start by creating a div with the class “grid-container” to wrap it. Screen Shot 2014-06-30 at 3.15.14 PM Next, we’ll make it so the logo spans 2 columns and the main-nav spans 8. Screen Shot 2014-06-30 at 3.16.31 PM Screen Shot 2014-06-30 at 3.16.18 PM We’ll then give the .main-nav a text-align of right. Something is wrong in my test file I can’t figure out so I’m using theirs.

Screen Shot 2014-06-30 at 3.23.16 PM Screen Shot 2014-06-30 at 3.22.48 PMNext we’ll do the columns. We’ll give the containing div the class .grid-container, then give the child divs the appropriate grid classes. We’ll have them total to 12 columns, making them nicely take up the whole width.

Screen Shot 2014-06-30 at 3.25.45 PM Screen Shot 2014-06-30 at 3.25.19 PM

 

To add a new row of content, simply repeat the process and give the parent div the class .grid-container and the child divs the grid class based on how many columns you want it to take up.

Screen Shot 2014-06-30 at 3.28.49 PMScreen Shot 2014-06-30 at 3.28.34 PMNow, we’ll want to prevent our layout from getting too wide on larger viewports widths. We’ll add a new media query for that, and make it so that if the screen is at least 1200px wide, the .grid-container’s max width will be 1100px. Just like a normal wrapper we’ve done a bunch of times before.

Screen Shot 2014-06-30 at 3.31.20 PMScreen Shot 2014-06-30 at 3.31.44 PM

Next, we’ll create a visibility class that hides elements in mobile devices with a preexisting media query. We’ll add a new class called .hide-mobile and apply it to the elements we want to hide on smaller viewports.

Screen Shot 2014-06-30 at 3.34.59 PM  Screen Shot 2014-06-30 at 3.34.51 PM Screen Shot 2014-06-30 at 3.34.46 PMScreen Shot 2014-06-30 at 3.35.13 PM

And just like that, I’ve finished the CSS sections. I can’t believe I finally got this far. I started the treehouse courses on April 11, 2014, and now, just 80 days later, I’ve crushed the lessons and am onto Javascript. When I started the CSS foundations it seemed almost impossible, so much to learn and go through. I’m really proud to have gotten this far, but there’s still a ways to go.

New terms from treehouse – CSS Layout Techniques Part 2 – Positioning Schemes and Flexbox Layout

Positioning Schemes

Relative Positioning

In this example we’ll use relative positioning to set up the header. We start with this:

Screen Shot 2014-06-24 at 2.10.59 PM

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.

Screen Shot 2014-06-24 at 2.14.49 PMScreen Shot 2014-06-24 at 2.13.30 PM

Now, if we were to style the logo bottom:20px;, it would offset it 20px up from the bottom from its original position.

Screen Shot 2014-06-24 at 2.16.57 PM Screen Shot 2014-06-24 at 2.16.50 PMIf we were to change it to top:20px;, it would move it 20px from the top.

Screen Shot 2014-06-24 at 2.17.59 PM

Screen Shot 2014-06-24 at 2.18.05 PM

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.

Screen Shot 2014-06-24 at 2.19.44 PM

Screen Shot 2014-06-24 at 2.19.59 PM

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;.

Screen Shot 2014-06-24 at 2.22.29 PMScreen Shot 2014-06-24 at 2.22.37 PM

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.

Screen Shot 2014-06-24 at 2.25.01 PM

The best way to fix this is by giving the header an overflow value of hidden.

Screen Shot 2014-06-24 at 2.27.19 PM Screen Shot 2014-06-24 at 2.27.08 PM


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:

Screen Shot 2014-06-25 at 9.38.28 AM

First, we need to establish the header container as position:relative. Then we’ll set the logo and nav elements as position:absolute;

Screen Shot 2014-06-25 at 9.42.20 AM Screen Shot 2014-06-25 at 9.42.08 AM

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…

Screen Shot 2014-06-25 at 9.45.18 AMScreen Shot 2014-06-25 at 9.45.30 AM

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.

Screen Shot 2014-06-25 at 9.47.55 AMScreen Shot 2014-06-25 at 9.48.05 AM

We’ll use offsets now to position the elements.

Screen Shot 2014-06-25 at 9.49.47 AM Screen Shot 2014-06-25 at 9.49.36 AM

Now, let’s say we wanted to put the nav items on the right.

Screen Shot 2014-06-25 at 9.51.18 AM Screen Shot 2014-06-25 at 9.52.08 AMThe 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:

Screen Shot 2014-06-25 at 9.53.18 AMScreen Shot 2014-06-25 at 9.53.25 AM

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.

Screen Shot 2014-06-25 at 9.55.15 AMLike 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.

Screen Shot 2014-06-25 at 9.59.42 AM Screen Shot 2014-06-25 at 9.59.28 AM

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.

Screen Shot 2014-06-25 at 10.01.57 AM Screen Shot 2014-06-25 at 10.01.46 AM

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.

Screen Shot 2014-06-25 at 10.03.53 AM Screen Shot 2014-06-25 at 10.03.46 AM

We can also now add more content above and below, and also remove the wrapper styling without breaking the layout.

Screen Shot 2014-06-25 at 10.06.43 AMScreen Shot 2014-06-25 at 10.06.50 AM


Fixed Positioning

Best example of this is with a fixed header. Once again, we’re starting with this:

Screen Shot 2014-06-25 at 10.48.13 AM

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.

Screen Shot 2014-06-25 at 10.51.46 AM  Screen Shot 2014-06-25 at 10.51.19 AM

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.

Screen Shot 2014-06-25 at 10.54.06 AM Screen Shot 2014-06-25 at 10.53.44 AM

If we wanted the header to be at the bottom of the page, you’d simply change it to bottom:0;

Screen Shot 2014-06-25 at 10.55.09 AMScreen Shot 2014-06-25 at 10.55.33 AM

 

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.

Screen Shot 2014-06-25 at 10.51.37 AM

To fix this, add some top padding to the body of the page. Since the header is 100px tall, we’ll use 100px.

Screen Shot 2014-06-25 at 10.59.35 AM Screen Shot 2014-06-25 at 10.59.28 AM


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.

Screen Shot 2014-06-25 at 11.07.40 AMFirst, 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.

Screen Shot 2014-06-25 at 11.09.25 AM

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.

Screen Shot 2014-06-25 at 11.34.19 AMScreen Shot 2014-06-25 at 11.33.47 AM

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.

Screen Shot 2014-06-25 at 11.36.29 AM

Screen Shot 2014-06-25 at 11.36.13 AM


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:

Screen Shot 2014-06-27 at 12.34.08 PM

Notice how the header logo has been added as a list item to the main nav. This will make it easier for us later.

Screen Shot 2014-06-27 at 12.34.14 PM

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.

Screen Shot 2014-06-27 at 12.40.24 PMScreen Shot 2014-06-27 at 12.40.37 PM

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.

Screen Shot 2014-06-27 at 12.39.45 PMScreen Shot 2014-06-27 at 12.39.54 PM

Next we’ll give them some margin left and right.

Screen Shot 2014-06-27 at 12.42.47 PM Screen Shot 2014-06-27 at 12.42.37 PM

 

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.

Screen Shot 2014-06-27 at 12.49.06 PMScreen Shot 2014-06-27 at 12.49.18 PM

For now, we’ll keep it at 50px.

Screen Shot 2014-06-27 at 12.50.23 PMScreen Shot 2014-06-27 at 12.50.27 PM

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.

Screen Shot 2014-06-27 at 1.14.04 PM Screen Shot 2014-06-27 at 1.13.58 PM

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.

Screen Shot 2014-06-27 at 1.15.06 PM Screen Shot 2014-06-27 at 1.14.04 PM

For this to work in Safari, we must copy the flex declarations and use the -webkit- prefix.

Screen Shot 2014-06-27 at 1.17.58 PM

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.

Screen Shot 2014-06-28 at 12.26.36 PM

Screen Shot 2014-06-28 at 12.28.41 PMScreen Shot 2014-06-28 at 12.26.44 PMThey’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.

Screen Shot 2014-06-28 at 12.34.09 PMScreen Shot 2014-06-28 at 12.34.19 PM

Next, we’ll position them with a left:-30%;, and add an overflow:hidden to the nav links, to hide them.

Screen Shot 2014-06-28 at 12.36.14 PMScreen Shot 2014-06-28 at 12.36.37 PMScreen Shot 2014-06-28 at 12.36.23 PMScreen Shot 2014-06-28 at 12.36.28 PMNow, 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.

Screen Shot 2014-06-28 at 12.39.45 PMScreen Shot 2014-06-28 at 12.39.54 PM

We’ll add a transition to make it look nicer.

Screen Shot 2014-06-28 at 12.41.28 PMaa

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.

Screen Shot 2014-06-28 at 12.45.31 PMaassThe transition also works on mobile devices.

sss

 


Flexbox Columns

Now we’ll layout the three columns with flexbox. Starting with this:

Screen Shot 2014-06-28 at 12.51.01 PM

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.

Screen Shot 2014-06-28 at 12.50.54 PMScreen Shot 2014-06-28 at 12.51.08 PM

To have the columns be evenly distributed, we can give them a flex value of 1.

Screen Shot 2014-06-28 at 12.53.10 PMScreen Shot 2014-06-28 at 12.53.22 PM

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.

Screen Shot 2014-06-28 at 12.54.47 PM Screen Shot 2014-06-28 at 12.55.19 PM

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.

Screen Shot 2014-06-28 at 12.57.22 PM Screen Shot 2014-06-28 at 12.57.06 PM

To swap the extra and secondary content ones, select the extra content and give it an order of 1.

Screen Shot 2014-06-28 at 12.58.25 PMScreen Shot 2014-06-28 at 12.58.33 PM

Lastly, once again we need to include the vendor prefixes so it works in Safari.

Screen Shot 2014-06-28 at 1.00.16 PM


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.

Screen Shot 2014-06-28 at 1.04.32 PM

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.

Screen Shot 2014-06-30 at 2.17.39 PM

Screen Shot 2014-06-30 at 2.21.05 PM

 

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.

Screen Shot 2014-06-30 at 2.24.59 PM

Next, we’ll fix the columns.

Screen Shot 2014-06-30 at 2.26.29 PM Screen Shot 2014-06-30 at 2.26.59 PM

Lastly, we’ll fix the icons by adjusting their position when you hover.

Screen Shot 2014-06-30 at 2.28.17 PM Screen Shot 2014-06-30 at 2.28.08 PM