CSS Positioning & Floats

Created Sunday, 30 September 2012 23:11 Last Modified Sunday, 23 June 2013 15:21

So far in this class, we've been changing the look of our html elements with css, but we haven't really been making them move around the page. It's time for us to take the next step forward and learn two ways we can change the arrangement of our page using CSS: with positioning and floats.

Before we begin: understanding the css properties of 'position' and 'float' are probably going to be the hardest concept to understand and master in this class. I expect that you'll probably experience difficulty learning these concepts, so don't be afraid if you don't get it right away.

CSS Positioning

There are five possible values you can assign using the css 'position' property. They are 'static', 'relative', 'absolute', 'fixed', and 'inherit'. For this assignment, I want you to worry about understanding 'static', 'relative', and 'absolute'. Let's take a minute to explain what each of these does.

position: static;

Static positioning is really simple: if you have 2 elements, and they are both have 'position: static', then the elements will appear on top of each other in the order they appear in the html document. Static positioning can also be pretty boring - most of the websites we see don't use a one-column layout to display their content. You should note that static is the default position value, which means that if you don't assign a different value, the element will be positioned statically. Take a look at the example code below:

<ul class="staticExample">
    <li class="first">First</li>
    <li class="second">Second</li>
    <li class="third">Third</li>
    <li class="fourth">Fourth</li>
</ul>

We'll go ahead and assign a width and 'margin: 0 auto' to .staticExample make the list appear in the center of the page. We'll also assign the list items inside of .staticExample, a width of 200px and a height of 100px. Then, we'll give each list item a seperate background color. Remember, we don't actually have to assign 'position: static' because it is the default behavior:

.staticExample {
    max-width: 800px;
    margin: 0 auto;
    background: #ff3;
}
.staticExample li {
    width: 25%;
    height: 100px;
}
.first {
    background:#0d24ff;
}
.second {
    background:#ff0d0d;
}
.third {
    background:#66ff99;
}
.fourth {
    background:#ccc;
}

The code will render in the browser like this, with each element stacked on top of the other in the order they appear in the html (pretty boring, huh):

  • First
  • Second
  • Third
  • Fourth

Elements assigned 'position: static' can not be given the css properties 'top', 'bottom', 'left', or 'right'. Elements that have 'relative', 'absolute', or 'fixed' positioning can have these properties applied. Let's move on to these more useful and interesting properties.

position: relative;

Relative positioning is a little bit harder to understand. Unlike 'position: static', if an element has 'position: relative', it can be assigned css properties for 'top', 'bottom', 'left', and 'right'. To explain what these properties can do, we'll change the name of our .staticExample to .relativeExample:

<ul class="relativeExample">
    <li class="first">First</li>
    <li class="second">Second</li>
    <li class="third">Third</li>
    <li class="fourth">Fourth</li>
</ul>

We'll also assign list items inside of .relativeExample a position of relative, a width of 200px and a height of 100px. Then, we'll give each list item different left position values:

.exampleNav {
    max-width: 800px;
    margin: 0 auto;
    background: #ff3;
}
.exampleNav li {
    position: relative;
    width: 25%;
    height: 100px;
}
.first {
    background:#0d24ff;
    left: 0px;
}
.second {
    background:#ff0d0d;
    left: 25%;
}
.third {
    background:#66ff99;
    left: 50%;
}
.fourth {
    background:#ccc;
    left: 75%;
}

The example written above would render in the browser like this:

  • First
  • Second
  • Third
  • Fourth

The 'left' value of each block makes the left-most edge of each list item appear the assigned value to the left of where the object would appear if it had 'position: static;' (if all of our blocks in this example had a 'position' of static, they would appear on top of each other, and we would be unable to assign these 'left' values.)

It's important to note that the vertical positioning (the 'top' and 'bottom' values) will be relative to where the object would appear if it had 'position: static'. For the sake of this example, I'll write a css class that assigns the value 'top: 100px' to our Second element (the red block.). The only change in the html is done to this line:

    <li class="second top100">Second</li>

The additional css class looks like this:

.top100 {
    top: 100px;
}

  • First
  • Second
  • Third
  • Fourth

You'll notice that there is an empty white space where the second list item was in our first example, and that the second list item is now horizontally aligned with our third block. The top of the list item assigned .top100 is 100px from the top of where it would be if it had 'position: static'.

What do you think will happen if we write a class that assigns a property of 'bottom: 100'? Let's take a look at an example. I'll go ahead and assign a class to the third list item, the only line changed is here:

    <li class="third bottom100">Third</li>

The css class is also very simple:

.bottom100 {
    bottom: 100px;
}

The code renders in the browser like this:

  • First
  • Second
  • Third
  • Fourth

Now the third element's bottom is 100px above where the element would be if it had 'position: static'.

position: absolute;

Absolute positioning adds even more control over where we want to position our elements. Whereas we could use 'position: relative' to assign an element horizontal and vertical values that changed its position relative to where it would be in the natural flow of the document, 'position: absolute' is used to assign an element a position inside of a containing element.

There are some tricky things to remember with absolute positioning: for one, if you don't have a containing element that has 'position: relative' or 'position: absolute' assigned, the containing element will be the body of the web page. So, if we wanted to use absolute positioning on the list items in our unordered list from above, we'd have to add this in the css:

.exampleNav {
    position: relative;
}

Now, let's use absolute positioning on our fourth block. We'll alter the html like this:

    <li class="fourth absoluteExample">Fourth</li>

We'll write some css:

.relativeExample li.absoluteExample {
    position: absolute;
    left: 10%;
    top: 50px;
}

The code in the browser would render like this:

  • First
  • Second
  • Third
  • Fourth

You'll notice that because our .absoluteExample has a top value of 50, and a left value of 100, it overlaps the bottom right fourth of our 'first' list item. You'll also note that the overall size our exampleNav has changed: it's now 600 pixels whereas in every previous example it was 800. These are both due to the absolute positioning of the element.

Absolute positioning is a bit tricky to get the hang of: you have to be aware that any elements with absolute position are taken out of the flow of the document, and that they can appear on top of (or below of) other elements. It will likely take some practice to get used to using absolute positioning.

In your css zen garden project, there are actually several div tags at the bottom of the body which could be used with absolute positioning for some neat tricks. Try assigning a background to some of these divs, then using absolute positioning to position your image somewhere on your page.

CSS Floats

Floats can be pretty tricky, but they are extremely useful. Let's take a look at an extremely simple example:

<ul class="floatExample">
    <li class="first">First</li>
    <li class="second">Second</li>
    <li class="third">Third</li>
    <li class="fourth">Fourth</li>
</ul>

To demonstrate the 'float' property, we'll assign all the list items inside of .floatExample a value of 'float: left'.

.floatExample {
    max-width: 800px; 
    margin: 0 auto;
}
.floatExample li {
    float: left;
    width: 25%;
    height: 100px;
}

The code will render in the browser as follows:

  • First
  • Second
  • Third
  • Fourth

You can see that 'float: left' puts our list items in a row from left to right. Now, let's override this with 'float: right' and see what happens:

<ul class="floatExample rightExample">
    <li class="first">First</li>
    <li class="second">Second</li>
    <li class="third">Third</li>
    <li class="fourth">Fourth</li>
</ul>
.floatExample.rightExample li {
    float: right;
}

The above code will render below.. Notice our 'first' list item is on the right, while our 'fourth' list item is on the left side.

  • First
  • Second
  • Third
  • Fourth

Floats can be extremely useful if we're trying to wrap text around an image. Take a look at the example below:

<div class="wrappedText>
<img src="/images/puppy-with-heart.jpg" alt="cute puppy with heart"/>
<p>I love lollipop tootsie roll sweet I love I love danish tart wafer. I love I love tiramisu. Powder I love jujubes tiramisu candy. Gingerbread sweet pudding bear claw. Jelly beans muffin I love biscuit caramels chupa chups. Marzipan chupa chups jujubes caramels macaroon pudding. Chupa chups I love pudding gummies chocolate apple pie toffee. Dragée jelly beans icing muffin apple pie topping jujubes gummies. Macaroon wypas gummies wafer biscuit wafer icing applicake soufflé. Toffee candy bonbon apple pie. Muffin jelly beans tootsie roll chupa chups. Cupcake fruitcake oat cake candy chupa chups topping chocolate bar danish pastry.<p>
</div>

We'll set the image to float to the right. We'll also do some stuff to the paragraph to over-ride the default styling that I've got assigned to paragraph tags on this website

.wrappedText {
    background: #ccc;
    max-width: 800px;
    margin: 0 auto;
}
.wrappedText img {
    float: left;
    background: #000;
}
.wrappedText p {
    text-indent: 0px;
    max-width: 800px;
}
.wrappedText img, .wrappedText p {
    padding: 5px;
    margin: 5px 10px;
}

The code will render in the browser like this:

cute puppy with heart

I love lollipop tootsie roll sweet I love I love danish tart wafer. I love I love tiramisu. Powder I love jujubes tiramisu candy. Gingerbread sweet pudding bear claw. Jelly beans muffin I love biscuit caramels chupa chups. Marzipan chupa chups jujubes caramels macaroon pudding. Chupa chups I love pudding gummies chocolate apple pie toffee. Dragée jelly beans icing muffin apple pie topping jujubes gummies. Macaroon wypas gummies wafer biscuit wafer icing applicake soufflé. Toffee candy bonbon apple pie. Muffin jelly beans tootsie roll chupa chups. Cupcake fruitcake oat cake candy chupa chups topping chocolate bar danish pastry.

There are some things you will need to be cautious of when using floats. For one, if a float is taller than the other elements inside of its container, and there are no elements below it, it will actually 'escape' the container. We can see this if we shorten our paragraph:

cute puppy with heart

I love lollipop tootsie

The above example is something that you'll usually want to avoid. To do this, you can either avoid using floats in these types of situations, or you can use a workaround. There are a lot of people who will complain that workarounds are bad, non-semantic code, and they're right, but sometimes (or in my cases, most times) you're on a deadline and you've got to use them. One workaround you'll see a lot is a clearfix. This is applied by using a css property we haven't examined yet called 'clear' on the last element of the container. let's take our short paragraph example and modify the html:

<div class="wrappedText>
<img src="/images/puppy-with-heart.jpg" alt="cute puppy with heart"/>
<p>I love lollipop tootsie roll sweet I love I love danish tart wafer. I love I love tiramisu.<p>
<div class="clearfix" ></div>
</div>
.clearfix {
    clear: both;
}
cute puppy with heart

I love lollipop tootsie roll sweet I love I love danish tart wafer. I love I love tiramisu.

The div with the class of clearfix may not have anything in it, but the 'clear' property still lets it 'clear' any elements that are above it. In addition to 'clear: both', you can set 'clear: right' or 'clear: left' to only clear elements on one side.

Floats can also be extremely useful when you want to display content in a sidebar. For example, take this:

<div class="exampleContainer">
    <div class="exampleSidebar"></div>
    <div class="exampleContent"></div>
</div>

We'll apply some css:

.exampleContainer{
    max-width: 800px;
    background: #ccc;
    margin: 0 auto;
}
.exampleSidebar{
    width: 25%;
    background: #00f;
    float: left;
}
.exampleContent{
    width: 75%;
    background: #f00;
    float: right;
}
.exampleSidebar, .exampleContent {
    height: 200px;
}

Here's our result:

Please note that the sum of the widths of our inside elements equaled the sum of our container, filling it. Now, let's take a look at a common error that will break our layout. Remember that in css box model math, padding is added to the overall width of an element. So, if we add a class that has padding to one of our inside elements without adjusting the width of the overall container, there won't be enough room for the elements to be displayed side by side and they will clear automatically:

<div class="exampleContainer">
    <div class="exampleSidebar extraPadding"></div>
    <div class="exampleContent"></div>
    <div class="clearfix"></div>
</div>
.extraPadding{
    padding: 20px;
}

I added the .clearfix at the end of the html so you would be able to see the #ccc background of the .exampleContainer containing our elements. Our example will look like this:

Additional Reading

When it comes to positioning and floats, this is really just the tip of the iceberg. There's a lot more that you can do with them than what I have shown you above, but I have tried to explain the basics as simply as I can, as well as show some common problems.

I encourage you to do a lot more reading. Here are some extra resources that can help you:

Web Analytics