CSS Essential Training

Christina Truong - LinkedIn Learning - October 2019

Chapter 5 - Layouts: Float and Position

Introduction Getting Started Core Concepts The Box Model Typography Layouts: Float and Position Layouts: Flexbox and Grid Advanced Selectors Fluid and Responsive Layouts Conclusion Resumes

Introduction to Float

Float has largely been superceded by both flex-box and grid layouts, but before they were introduced, it was probably the most popular method for achieving a typical page layout. Typically, floats would be used to design columnar layouts or, really, any layout that separated the viewport into different areas for different types of content. An example of this might be a layout where you have containers for the header, a sidebar, a main content window and a footer where the header and the footer both occupied the full page width but the sidebar and main content areas were side by side, the main content area being much wider than the sidebar.

Although float is probably not used much nowadays, it is important to be aware of it because you may still see it in older code and there may be some situations where it is still better to use float to position something, even if you don't use it for a full layout.

The float and clear Properties

Remember that the normal method a browser will use to display block elements is simply to stack them, one on top of the other in the sequence in which they appear in the HTML code. They are also displayed, by default, as full-width.

If you add a float property to an element, it is removed from the normal flow and this has two consequences. Firstly, the elements don't have to take up the whole width and if they don't, they will stack side by side when there is enough room.

The second thing to remember is that any element that comes after the floated element will actually come immediately after the most recent unfloated block element. Let's look at an example from codepen. Here, we have several block elements, an image followed by three paragraphs.

The HTML for this is

1 <div class="container">
<img src="https://picsum.photos/95?image=1019" alt="placeholder image">
<p>Long paragraph. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Pariatur voluptatem culpa accusantium blanditiis consequuntur. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Pariatur voluptatem culpa accusantium blanditiis consequuntur. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Pariatur voluptatem culpa accusantium blanditiis consequuntur. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Pariatur voluptatem culpa accusantium blanditiis consequuntur.</p>
<p>Short paragraph. Consectetur adipisicing elit. Pariatur voluptatem culpa accusantium blanditiis consequuntur.</p>
<p>Another paragraph.</p>
</div>

The CSS for this is

1 .container {

2 width: 600px;

3 margin: 0 auto;

4 border: 5px solid black;

5

6 p {

7 background: #CDCDCD;

8 padding: 10px;

9 }

All of the element are contained within a <div> with a class of container and a width of 600 pixels. The paragraphs have been given a grey background to make the different parts a little easier to see. Initially, there are no floats being used so we have the image and below that, the three paragraphs, all being displayed as block elements - this is confirmed by the fact that the grey backgrounds for the paragraphs extend to the full width of the container.

Note that the image lines up with the edges of the border so there is no margin. We will start by giving it a float property.

1 img {

2 float:left;

3 }

This doesn't change the position of the image which was already positioned on the left, but the paragraphs below have moved up so that the first paragraph occupies the same space as the image (or at least, it overlaps with the image). The text has flowed around the image and again, because there is no margin, the text is squished up against the edge of the image. We will fix that by adding a margin of 10 pixels all around to the image.

This gives us a little bit of space between the image and the text and also between the image and the border. With that gap, we can see that part of the paragraph is behind the image so the element isn't flowing around the image, but the content is.

The first paragraph is quite long and part of it is below the image. If we delete this, leaving just the two smaller paragraphs, we can see that the first paragraph has wrapped around the image and there is now some extra room between the bottom of the paragraph and the bottom of the image so the second paragraph has also moved up and is floating around the image. If we want that second paragraph to start after the end of the image rather than floating around it, we need to clear the floats.

Where you apply a clear depends on where you want your page to return to the normal flow and you will add it to that element (that is, you add it to the first element that you don't want to be floating.

In this case, it's a paragraph with a <p> tag. We can't use p as a selector because we only want to apply it to one of the paragraphs. Since that is the second paragraph, we can add a class which we will call clear to it's opening <p> tag and apply the following rule.

1 .class {

2 clear: both;

3 }

Note that you can clear either left or right floats or both, but it is common to see both used, even when there is only one float to remove, as we have here. In this case

1 .class {

2 clear: left;

3 }

has exactly the same effect. However, specifying both means that you don't have to worry about which float you want to remove. It is probably best, and I think most common, to use both whenever removing a float unless you have both left and right floats and you only want to clear one of them.

Since the float property removes an element from the normal flow, this will affect one or more elements following it until the floats are cleared. However, you may not need to use a clear since elements will return to the normal flow automatically once all of the space that the image would have occupied in the normal flow has been filled.

Float and Collapsed Container

You won't always have an element to apply the clear property to. There are several options to resolve this, but let's consider the implications for float before we do that. We saw in the codepen example how taking the floated element out of the normal flow affected the elements that followed. When we had two small paragraphs, both of the paragraphs were being affected by the float until we cleared this for the second paragraph. Now, let's say we removed another paragraph so that one of the small paragraphs remains. If we remove the first paragraph, the result would be the same as removing the float altogether, at least visually, since the only other element has a clear property.

On the other hand, if remove the second paragraph, the first paragraph will still wrap around the image since it doesn't have a clear property. Now, the height of the paragraph element is less then the height of the image and since there are no other elements in the page, the paragraph determines the 'height' of the page and so the image has a greater height than the page. Just to be clear, here, the height of the page is a reference to the total height of all the images in the normal workflow so it is where the next element would appear if we added one without giving it a clear property. In this context, it doesn't matter whether the new element is in the same container as the floated element, it really just matters where it appears in the normal workflow. These elements would stack as block elements as if the floated element wasn't there although any content will float around the floated element.

Consider an example where we have a container for a header which sits at the top of the page and occupies the full width. We then have a sidebar container below it occupying an area of the screen on the left so we use a float left property. To the right of this is a container for our main content and to finish with, we have a footer. The HTML might look like this.

1 <!doctype html>

2 <html>

3 <head>

4 <meta charset="utf-8">

5 <meta http-equiv="X-UA-Compatible" content="IE=edge">

6 <meta name="viewport" content="width=device-width, initial-scale=1">

7 <title>Float Demonstration</title>

8 <link href="float1.css" rel="stylesheet" type="text/css">

9 </head>

10 <body>

11 <section>

12 <div class="header">HEADER</div>

13 <div class="sidebar">SIDEBAR</div>

14 <div class="main-content">MAIN CONTENT</div>

15 <div class="footer">FOOTER</div>

16 </section>

17 </body>

18 </html>

Each of these sections has a class attribute to allow it to be styled and all of these elements are wrapped in <section> tags. This simplifies things because it means I can set the width on this container to, say, 1000 pixels, and use that as the basis for calculating the width of the sidebar and the main content are. I will give each of the four sections a different background colour and add a width of let's say 300 pixels to the sidebar and 700 pixels for the main content, so it should be easy to see if everything is where we expect it to be.

This page can be viewed as float1 (opens in a new tab). It doesn't look quite right because the header shows a width of 1000 pixels and the sidebar and main-content containers should total the same width but actually, it looks like main-content is much narrower than it should be. Also the footer isn't quite where it should be and it took me a few moments to realise that this is because I didn't put a float property on main-content. As a result, it is partially occupying the space that is occupied by the sidebar. This can be tricky to spot because the positioning of the text gives the impression that the main-content container is correctly positioned, but it is actually behind the sidebar container (partially) but the text has wrapped around and so it is giving the impression that we have a narrower than expected container.

I mentioned that the footer is also in the wrong place and this may require a bit of an explanation because it is, in fact, where I wanted it to be. This will be a little bit clearer once the float has been corrected. Rather than just correct, I have left float1.html as it is and made the change in float2.html because I think that this illustrates a couple of things. Principally, the type of error that you can get with floats, but I think equally importantly, it shows that the correct version in some ways looks more wrong than the original, but there is one very important reason for using the 'correct' method and I will explain that in a moment.

Now, if we look at the revised version in float2.html (opens in a new tab), we can see that the main-content container is occupying the correct amount of space. If you inspect it in both float1.html and float2.html, you will see that in both cases, the dimensions are the same (700x600) but we only see the full container in float2.html. In float.html, the footer still seems to be in the correct place which is not completely what I expected. This element has been stacked immediately under the footer. It is not surprising that we can see the text below the sidebar, because we know that it will wrap around the floated elements (sidebar and main-content) and if we look at it in browser development tools, it has dimensions of 1000x618 (to compare this, in float1.html, it has dimensions of 1000x18 because main-content didn't have a float property and so wasn’t removed from the normal flow and therefore the footer appears below it).

So, we fixed everything (it seems) by adding the float property to main-content so that the look is correct, but footer is still technically in the wrong place and we can fix that by adding a clear property to it. This revised version can be seen as float3.html (opens in a new tab). It doesn't look any different to the previous version, but if you inspect the element, you will see that it has the correct dimensions of 1000x18.

Now, although the last two versions of the HTML file look the same and we could fix the first version just as easily by changing the width of main-content to 1000 pixels (arguably more easily since only one property has to be changed), the method used in float3.html (more accurately, in its CSS file, float3.css) is that it is the only version of the page where two things are true.

• The elements look as though they are in the right place.

• The elements are where they appear to be (in other words, they are in the right place).

This is important because if they weren't, when we add more elements (if we do) they might not act in a predictable fashion. Equally important is the overflow property and if this were applied to any of these elements in float1.html or float2.html, the results would almost certainly not be what you would expect unless you had accounted for the fact that footer is lined up with the header at the top. Other properties may also be affected , but the simple truth is that as a developer, you want elements to appear exactly where you place them if you want to be able to fully control the appearance of your web page.

Having said that, we should now take a look at the overflow property in order to understand how this might be affected by elements not being exactly where they think we are.

To see how this is affected by the overflow property, I have added this to the footer element with a value of hidden in float2.html. Here, it looks as though the footer has disappeared. I will do the same with float3.html and this time the footer is exactly where we expect it to be.

So, what's happening here? I mentioned earlier that the size of an element is determined by the size of the content plus any padding and borders, which means quite simply that the more content you add, the larger the element will be. In this example, we have set dimensions for some of the elements, although not for the footer, and we have seen that depending on the floats, the height of the footer is either 18 pixels or 618 pixels. The content sets a height of 18 pixels, but when the element didn't have a clear property meaning that it was positioned just below the header, it expanded to 618 pixels because this was the size required to allow the content to flow around the floated elements (which both have a height of 600 pixels.

When the overflow property is added with a value of hidden, that doesn't happen. Any content that doesn't fit inside the element is hidden, the element itself remains the same size. If we open up the browser tools by right-clicking on any of the visible elements in float2.html, we can select the footer element and see that its dimensions are 0x18 pixels. This surprised me a little as I'm not 100% sure where the 0 comes from. I guess that we have a height of 18 pixels because the footer is a block element and therefore will occupy that amount of vertical space, but there is no visible content which gives us that 0 width.

Other possible values for overflow include auto which will give you scroll bars if the content overflows the container and scroll, always gives you scroll bars even when the content fits completely inside the container.

I think that understanding all of this makes it easier to understand how we can clear floats when there is no element to add a clear property to and I mentioned earlier in this section that there are three ways to do that. The first is to use the overflow property. I'm not completely convinced that this can be used to clear floats, but we did see that they helped us to see when an element was being hidden by the floated elements so they can be useful in showing where floats need to be cleared or where we need to add other properties to overcome the issue.

The second method is usually referred to as the Clearfix hack which involves adding a snippet of CSS to a parent element that forces any child elements to self-clear.

1 .clearfix:after {

2 content: "";

3 display: table;

4 clear: both;

5 }

The class name, clearfix, is a pesudo-class so the colon is not part of the class name. You need to add this class to the parent element. To test this, I have gone back to flat2.html where, you will remember, we didn't clear the float and I will add the clearfix class to that and will give the parent container, <section>, the clearfix class. The result is shown in float4.html.

To be honest, I don't really see any difference between this and the version where footer doesn't clear floats but also allows overflow. If you inspect the footer in this version, you will see that it has a height of 618 pixels so clearly the clear property has not been inherited.

The third method is to apply a display property with a value of flow-root to the parent.

1 .parent {

2 display: flow-root;

3 }

Christina mentioned this was currently in draft (at the time the video was recorded) and caniuse.com showed a figure of 72.2% for global support. Today, it seems to be better-supported with a global support figure of 93.7% so that's much better buy there is still no support in IE or other browsers, mainly on Android phones and iPhones I think.

The example on codepen might actually make things a little clearer. The HTML for this example is

1 <div class="container">

2 <div class="float">float me!</div>

3 <div class="float">float me!</div>

4 </div>

Here, we have a parent container with two child containers. The CSS will make it a little clearer.

1 .clearfix:after {

2 content: "";

3 display: table;

4 clear: both;

5 }

6

7 .container {

8 border: 2px solid black;

9 width: 500px;

10 margin: 0 auto;

11 /* overflow: hidden; */

12 /* display: flow-root; */

13 }

14

15 .float {

16 background: lightblue;

17 border: 1px solid white;

18 height: 60px;

19 width: 60px;

20 padding: 10px;

21 /* float: left; */

22 }

The child containers are both boxed with a blue background and the container is really just a black border with a width of 500 pixels. No height is specified, so the height is determined by the contents and this means that it is essentially the height of the blue boxes. Note that no floats have yet been applied.

If we enable the float on the boxes, we can see that the border around the boxes becomes a solid black line. Since the floats remove the boxes from the normal flow, the parent container no longer has any child elements that are part of the normal flow so effectively there are no contents and the height becomes 0.

There is no child element after these two boxes so there is nowhere to add a clear property. Each of the three methods to resolve this are in the CSS but the overflow and display methods are commented out and the clearfix hack is not being applied because we haven't added the class to the HTML.

If we uncomment the first two methods, one at a time, we see that the border surrounds the blue boxes again (for obvious reasons, only one of these should be enabled at a time). If we comment out both of these fixes and add the class of clearfix to the parent container, we get the same result

This suggests that I misunderstood what Christina meant by clearing the floats. I think what she actually meant was that the floats would still behave as normal, but the parent element wouldn't collapse to a height of zero and if we then add another element after the boxes, it should be displayed as normal - that is, it won't be behind the blow boxes and won't wrap around them. I added a paragraph to the HTML in codepen and that does seem to be the case, but only if the paragraph is outside of the element containing the blue boxes. So the floats have been cleared.

If the fix is removed so that the floats are no longer cleared and the parent container reverts to a height of zero, the paragraph added after the container lines itself up from the bottom of the container and therefore it does wrap around the floated elements.

The mistake I made earlier was to think that any elements added after the floated items would no longer be affected if, for instance, the clearfix hack was in use, but it doesn't clear the floats inside the parent and that's why the footer was unaffected. In reality, this simply meant that the parent container had the expected height so we could safely add elements after the it.

Layouts and the Box Model

Earlier, we looked at how the size of a container included any padding and border sizes, but not margins. But although margins don't increase the size of an element, it does have an effect on the amount of space that the element occupies in the page. We also saw an example of a layout using floats and you may recall that the width of the parent container was set to 1000 pixels, with the width of the floated elements being 300 pixels and 700 pixels so they could fit snugly into the container, side-by-side.

If we change the size of these elements, this will no longer be the case and they may either not occupy the whole width or we may find that the second of the floated elements is pushed down to the space below the first floated element. As a reminder, the most recent version of our example was float4.html, and this doesn't include any padding (or margins).

I have added padding of 10 pixels all round to both of the floated elements and the results can be seen in float5.html. We can see that the main-content container has been pushed down to the line below.

This can easily be fixed by adjusting the dimensions of the containers until they fit neatly together again. This should be easy enough to do since we know that the problem has been cause by the padding so we just need to reduce the width of the containers by the amount of space occupied by that padding. The problem with this is that any time we change these values, we need to resize the containers again to account for that.

A better solution is to change the way that the browser calculate the size of the element and we can do this via the box-sizing property. If we give this value of content-box, this means that the size of the element is based on the size of the content and this is the default value, so it means that padding is added to the overall size (as is the border) but not the margin.

If we use a value of border-box for box-sizing, the result will be that the element will occupy the amount of space specified. For instance, the sidebar in our example has a width of 300 pixels and the main-content area has a width of 700 pixels so that is 1000 pixels total width plus padding (because the box-sizing property has the default value). If we change the box-sizing property to border-box, they will occupy a total width of 1000 pixels, even if we then add or change the amount. So the sidebar, for instance, has a width of 300 pixels without any padding and a width of 300 pixels after the padding has been added. So, we don't see the problems we saw with float5.html.

In float6.html, I have added padding of 10 pixels to both of the floated elements and we can see the padding, but as expected, the main-content area is below the sidebar. I will add the box-sizing property to both the elements and the result is shown in float7.html. So, we can still see the padding around the floated elements, but this hasn't increased the size of the elements so they still fit quite neatly together.

In float8.html, I have added margins around the floated elements and as you can see, they are now out of position with the main content area being below the sidebar. So, this fix avoids any issues with the padding, but we still need to be careful when adding or adjusting margins around floated elements.

There are a couple of additional points I'd like to make. This fix is known as the Box Model Fix and it can be applied to a whole site, rather than individual elements, by adding this little bit of CSS to a stylesheet used by the whole site (assuming you have one, which I think you should because there will always be some rules that you just want to apply everywhere).

1 /* border box fix */

2 html {

3 box-sizing: border-box;

4 }

5

6 *, *:before, *:after {

7 box-sizing: inherit;

8 }

Another important point is that since this fix is applied to elements where floats are being applied, effectively it is fixing the problems associate with a float-based layout, you may not use it yourself and may only really see it in legacy code. Nevertheless, it is important to be aware of it and there may be situations where you will find it useful. However, if you are not using a float-based layout and you find that you need to use the fix because you have used floats in a part of your code, you will probably want to use it in the way that is demonstrated (that is, by applying the box-sizing property to specific elements) rather than using the global fix described above.

Although I didn't use it, there is a codepen example for this exercise which includes a couple of links to more information on the Box Model Fix. The first is to a posting by Paul Irish who first documented the fix and the second it to a posting by Chris Colyeron CSS Tricks.

Project: Float and Box Model Fix

Now that we have seen the Box Model Fix, we are going to add this to the resume. The CSS for the fix is added in the global section before the body selector. Christina recommends that this is added to the base CSS of all your projects, but I don't (at the moment, at least) use floats in my personal projects so I'm not completely convinced of that. If you do use floats, or you want to have the flexibility to add them to your projects later, then it would be worthwhile to add the fix.

The resume isn't using floats, but we will change that now. The intention is to add floats to the project items to allow the image to float to the left and have the text flow around it. We will create a class to be used as a selector (called project-item), and we will add that class name to each project block.

We will use this selector to style just images inside the project-items so we will use a descendant selector and apply a float of left, and this will go at the bottom of the projects section in the CSS.

1 .project-item img {

2 float: left;

3 }

In the resume, we can see that the text is now flowing around the images in the projects section, but the text in the first project item is a little short and it has left some space at the bottom that the second project item has moved into and we can see that in resume9/.html.

We are going to have to apply a clear, but we can't apply it to the paragraph or to the image, because either would prevent the text from flowing round the image, so we are going to have to use one of our self-clearing methods.

The floated element is the image (or images) and the parent element is the section to which we added the project-item class. We will use this as a selector and put it just before the CSS rule to float the images. The property we will use is overflow which we will set to hidden.

1 .project_item {

2 overflow: hidden;

3 }

This clears the floats, but there is no space between the images and text text flowing around them. To fix this we will add a margin of 20 pixels to the right side of the images. We will use the same descendant selector as the one we had used to set the float property. You may also notice that the images created breaks between the text so it was quite clear where the different projects were, but not that the text is floating around the images, we don't have that kind of separation. To fix this we will add a border to project-item, but only to the bottom.

This will draw a dashed line under each of the project items and the colour is the dark gray (almost black) colour used for the text colour, and to ensure that there is some space between this border and the surrounding elements, we will add some padding to the top and bottom (25 pixels).

1 .project-item {

2 border-bottom: 1px dashed #343434;

3 padding: 20px 0;

4 }

This looks much better now and we can see that in resume10.html. This seems to be fine, but now that the text is flowing around the image, we have the title over the image with the text to the right. It would probably be better to have the title with the text and to fix this, we need to make a change in the HTML. Consider the following snippet from resume10.html.

1 <!-- Project 1 -->

2 <section class="project-item">

3 <h3>Lynda / LinkedIn Learning Courses</h3>

4 <img src="images/project-courses.jpg" alt="course thumbnail">

5 <p>Developed content and instruction for various CSS and front-end focused web development courses including CSS Essential Training, Getting Your Website Online, Design Systems & Architectures and more.</p>

6 <a class="btn" href="https://www.linkedin.com/learning/instructors/christina-truong?u=2125562" target="_blank">LinkedIn Learning</a>

7 <a class="btn" href="https://www.lynda.com/Christina-Truong/7842227-1.html">Lynda.com</a>

8 </section>

This is the first project in the projects section and you can see that we have the heading, then the image and then the paragraphs. What we want is for both the heading and the paragraphs to flow round the image and we can achieve that quite simply by changing the order of the elements as follows:

1 <!-- Project 1 -->

2 <section class="project-item">

3 <img src="images/project-courses.jpg" alt="course thumbnail">

4 <h3>Lynda / LinkedIn Learning Courses</h3>

5 <p>Developed content and instruction for various CSS and front-end focused web development courses including CSS Essential Training, Getting Your Website Online, Design Systems & Architectures and more.</p>

6 <a class="btn" href="https://www.linkedin.com/learning/instructors/christina-truong?u=2125562" target="_blank">LinkedIn Learning</a>

7 <a class="btn" href="https://www.lynda.com/Christina-Truong/7842227-1.html">Lynda.com</a>

8 </section>

Now, the image is first and everything after this is being affected by the float, so both the heading and the paragraphs will flow round the image and the heading will be directly above the rest of the text in that section.

I have done that for each of the project items and, as you can see in resume11.html, the result does look better. I should stress, however, that this is a design choice and you may prefer the previous version, but I think that it does make sense when the text is flowing around the image like that, to have heading more closely associated with the text. Without the float, when we had the heading with the image below it and the paragraphs below the image, it made more sense to have the heading first.

The important point, though, is that with floats, you may need to think a bit more about the order of the HTML elements and, particularly, what order is required to get the best look in the browser.

One final point on this, and again, I think that it provides a nice illustration of how small tweaks to the CSS or the HTML can make a big difference to a page. If you look at resume11.html, you might notice that there is a gap above the heading which means that it doesn't perfectly line up with the top of the image. To fix this, we are going to apply a top margin of 0 to each of the three <h3> headings in the project items. Since we only want to target the headings inside the project items, we will use a descendant selector where the parent is project-item, like this.

1 .project-item h3 {

2 margin-top: 0;

3 }

Since it matches the order of the HTML better, we will put this after the descendant selector, .project-item img, we used to apply the float to the images. The result is shown in resume12.html

One final point to make here is that the text in each of the project items, the text fits quite neatly next to the image given us quite a neat layout which is effectively in 2 columns. We can quite easily spoil this! The reason why I might want to do that is to demonstrate the fact that with different amounts of text, the look of the page can change and so we want to look at how to remedy that. I will create a slightly different version of the resume which is only for the purpose of making this point so I will give it a different name. I will create it by duplicating some of the text in the first project item so we will call it extratextresume1.html.

The text has filled in the area to the right of the image and there is a little bit left over which is appearing under the image, so this is spoiling the two-column look we had. To fix this we will need to create a couple of containers, one will hold the image and the other will hold the other elements in that project-item. We then need to apply float to both of these containers. To do this, I created a <div> around the image and another to gold the paragraphs and the links and I gave them a class of float. I then removed the float from the image and used the float class as a selector and applied the float there, with the result shown in extratextresume2.html.

If floats are still used today, it would be most likely for floating text around an image in this way rather than for creating a layout, so we haven't covered in perhaps as much detail as we could have. If you want more detail on using floats to create a layout, you can get that from another of Christina's courses, CSS Layouts: From Float to Flexbox and Grid. This is from September 2019 so it is fairly up-to-date and it has sections on floats, flexbox and grid. There is also a course by Morten Rand-Hendriksen called CSS: Advanced Layouts with Grid, which was published in April 2019. It is a longer course than Christina's and because it restricts itself to the Grid layout, it is going to cover it in more detail. I'm inclined to say that after doing this course, it would be worth checking out CSS Layouts: From Float to Flexbox and Grid to see what additional information is covered there and it would probably be worth studying CSS: Advanced Layouts with Grid in more detail.

Position

Like floats, we can also use the position property to change the flow of the page. The possible values are

• static - this is the default value and means that the element follows normal flow - that is, it is not positioned.

• absolute - the element is positioned relative to the first positioned (not static) ancestor.

• fixed - the element is positioned relative to the browser window which means that as you scroll down the page, for example, it remains in position.

• relative - the element is position relative to its normal position, so this is really just moving the element slightly over from its normal position. It is the only value, other than static, that doesn't remove the element from the normal flow.

• sticky - combines fixed and relative. The element will be positioned relative until a specified offset position in the viewport is reached, it then sticks in place as though it were positioned as fixed. Thus in IE or Edge (at least up to version 15). It is supported in Safari with a webkit prefix. At time of writing, it is still a Working Draft - see caniuse.com - sticky

• initial - sets the property to its initial value.

• inherit - inherits the property from its parent element.

• More information on the position property can be found at W3 Schools website.

Note that, aside from static, you must specify an offset from the top, bottom, left or right. Usually this will be a pair, for example from top and left. A typical CSS rule would look like this.

1 .box {

2 position: relative;

3 top: 10px;

4 bottom: 10px;

5 }

This might seem a little bit confusing, so let's look at the example on codepen.io. The HTML for this is

1 <div class="wrapper">

2 <div class="parent">

3 <div class="box relative">relative</div>

4 <div class="box absolute">absolute</div>

5 <div class="box fixed">fixed</div>

6 </div>

7 <div class="box sticky">sticky</div>

8 <p>Just a bunch of text for ............<p>

9 <div class="wrapper">

10 <p>Second wrapper.</p>

11 <p>Just a bunch of text for .........<p>

12 </div>

We have two containers with the class wrapper. The second contains a lot of text which is just being added for demonstration purposes, so that there is enough in the page to make scrolling possible. I have omitted most of the text in the above code because it's not relevant to the overall structure of the page which is what we are interested in. The first wrapper contains three boxes, labelled relative, absolute and fixed. There is also a fourth box labelled sticky which is between the two containers so it is not in either one. All four boxes are 60 pixels by 50 pixels and have a background colour so that we can see them more easily. Note that there is also around the first wrapper, so we have the first three boxes inside this border, then the fourth box followed by the text.

We will start by adding a position property to the relative box.

1 .relative {

2 position: relative;

3 top: 10px;

4 right: 10px;

5 }

The result is that the box is pushed down (10 pixels from the top of its previous position) and left (30 pixels from the right of its previous position). That seems a little strange and counter-intuitive to me. I expected it to be either moved 30 pixels to the right or to a position 30 pixels away from the right edge. This is actually made a little clearer on the W3 Schools page which notes that the specified value adds, in this case, 30 pixels to the right position making it 30 pixels further away from the right edge, which does make sense when you consider that this is an offset.

Next, we will add an absolute position to the absolute box.

1 {

2 position: absolute;

3 }

This doesn't change the position of the absolute box, but the fixed box has disappeared.

This is because the absolute box has been removed from the normal flow and as a result, the fixed box (and everything after it) has been moved up to occupy the space within the normal flow that had previously been occupied by the absolute box. If we override the width of the fixed box and add, say 30 pixels to it, we can then see part of it behind the absolute box.

Remember that elements with absolute positioning are positioned relative to the close positioned ancestor relative, or to the body if there is no ancestor with a position property. Let's see what happens if we give it an offset.

1 .absolute {

2 position: absolute;

3 right: 25%;

4 bottom: 5%;

5 }

Here, we have given it an offset of 25% from the right and 5% from the bottom, bit since none of it's ancestor elements have a position value, this is relative to the browser which gives it an initial position near the bottom and towards the right of the screen. This differs from relative positioning in that the positioning does seem to be a little more intuitive. The starting position is 5% from the bottom of the screen and 25% from the right edge. As a matter of interest, I checked whether this was because we were specifying the offset in percentages by changing the values to 350 pixels right and 50 pixels bottom and the position was more or less the same. Note that when the page is scrolled, the absolute box moves with it, so it is not in a fixed position.

When you are using absolute position, you will normally want it to be positioned within a specified area. In other words, you want it to be positioned within a container for example and the way to achieve that would be to add a position property to an ancestor element. In this case, the absolute box has two ancestors (apart from body or HTML) and these are wrapper and the parent. We can add any positioning value to the ancestor element, but since relative doesn't remove that container from the normal flow, it is usually a good choice.

If we add a position property to the wrapper with a value of relative, we can now see that the absolute box is positioned near the bottom of the wrapper. If we then add the same property and value to the parent container, since this is the closes ancestor, it overrides the property in the wrapper and the absolute box is positioned relative to the parent. Remember that the parent element is the one that contains three of the boxes and is surrounded by a red border.

In some ways, the fixed position is similar to the absolute position, but it is always positioned relative to the viewport, regardless of whether any ancestor elements have a position property and it it remains in position when the page is scrolled. If we add this to the fixed box with a position of 0 top and 0 right, the box immediately changes position to the top right corner of the screen.

1 .fixed {

2 position: fixed;

3 top: 0;

4 right: 0;

5 }

When the page is scrolled, the fixed box remains in the same position.

The sticky position looks a little weird and may take some getting used to. If we add a sticky positioning to the sticky box and give it an offset of 10 pixels from the top, it doesn't immediately change position.

1 .sticky {

2 position: sticky;

3 top: 10px;

4 }

If we start to scroll down the page, initially, the sticky box scrolls with the page, until it reaches the offset, 10 pixels from the top of the page. It then appears to become fixed and remains in that position as we continue to scroll. However, if we scroll past the bottom of its containing element, it is no longer fixed and it will disappear if you continue to scroll down.

It is possible to use position to produce a page layout, but it isn't really designed for that and is not recommended for that type of use because of the fact that, in most cases, it removes the element from the normal flow. It can be useful for styling specific elements such as a navigation bar that you want to have permanently in the same position.

Position and Z-Index

Elements within a container are stacked both vertically and horizontally as we have seen, but they are also stacked along the z axis, like layers similar to those in Photoshop. You can only see this when elements overlap. This is referred to as the stacking context, with elements having a higher z-index being stacked on top of elements with a lower index. Let's look at an example on copdepen.io. The HTML for this is shown below.

1 <div class="block1">block 1</div>

2 <div class="block2">block 2</div>

3 <div class="float">

4 <p>float</p>

5 <span class="inline">inline</span>

6 </div>

7 <div class="position">position</div>

I should point out that the <body> and <html> elements are always at the bottom of the stack since all other elements are placed on them.

The CSS that we start with for this exercise is

The CSS for this exercise.
The CSS for this exercise.

You can also see this in a browser at z-index1.html.

After the <body> and <html> comes the block level elements in the order in which they appear in the HTML, so if two elements overlap, the one that appears later in the HTML will, by default, be on top. Here, we have 4 <div> containers and in order, these are block 1, block 2, float and position. Float also contains an inline <span> element called inline (note that the names of these elements is based on the class given to each of them. Aside from float, the containers are more or less just coloured boxes with one word of text to (the class name) to identify them.

None of them are visible initially because they all have a display property set to none so they are hidden. Note that the <html> element has a gray background colour and <body> has a background colour of white so we can see that it is sitting on top of <html>.

If we remove the display property from block 1 and block 2, they both become visible and block 2 is on the top of block 1. This is because of the order in which the elements appear in the HTML. We can see this in z-index2.html.

Floated elements appear on top of non-floated elements (mostly) as we will see if we remove the display property from float and inline. This is shown in z-index3.html.

Finally, positioned elements are placed on top of floated elements (assuming the floated elements have not been positioned). If we remove the display property from the position box, we can see, in z-index4.html, that the position box is on the top.

In terms of how elements are positioned on top of each other, everything we have seen so far has followed the default ordering, so this is the result we would see if we didn't do anything to change these defaults. To do that, we would need to apply a z-index value to the an element that is higher than the value being applied to the element we want it to appear on top of. However, it is important to remember that we can only apply a z-index value to a positioned element.

Let's assume that we want to see block 1 being displayed on top of anything else. We can start by giving it a position property with a value of relative, since this will not remove it from the normal flow. This gives us the result shown in z-index5.html. This is without adding a z-index, but remember that, in the default order, positioned elements appear above any others except other positioned elements that appear after it in the HTML. The position box is after block 1 in the HTML, so it is still positioned on top of block 1.

You may have noticed, if you inspected any of these elements, that there is a z-index value for each one specified as auto. We can add any integer value as this z-index but I would guess that everything has, by default, a value of 0 and I am assuming that when we talk about the default order, which we have seen in the previous examples, that this order is applied to all elements with the same value. For example, if we apply a z-index of 0 to block 1, nothing changes. If we add a negative number, it disappears behind the body and the HTML. If we give it a positive value, which can be as little as 1, it then appears on top of the position box and we can see that in z-index6.html.

If we want to stack more items than this, we can follow this simple process to add a position property, if necessary and then add a z-index value that is higher than that given to the element you want to place it on top of, bearing in mind that any positive integer will place it on top of any other element that doesn't have a z-index property with a higher number.

I should just add that when we talked about position, we mentioned that one possible value for the position property is static, which is the default and essentially means that no position is being applied. Now, of you add a z-index property to an element that does not have a position property, the z-index is ignored. If it does have a position property with a value of static, it is still ignored so the only option, if you don't want to remove the element from the normal flow, is to use a relative position.

There will probably not be very many occasions when you would use the z-index property, but it is useful when you want to ensure that something is displayed on top of any other elements but this would usually be temporary. Examples might include a drop-down menu, a tooltip or a pop-up box so you might have the z-index set using a pseudo-class such as hover. For instance, if you have a tooltip, you might position it behind the body with a negative z-index value, but change it to a positive value when a particular element is hovered over so that it only appears when the user hovers over that element.

To demonstrate this, I have added another element to the HTML file.

1 <div class="block1">

2 block 1

3 <span class="tip">This is block 1</span>

4 </div>

This has been styled as follows.

1 .tip {

2 z-index: -1;

3 position: relative;

4 color: red;

5 background: antiquewhite;

6 top: 0;

7 right:0;

8 font-size: 8px;

9 }

There is also a CSS rule applied when the user hovers over it. Notice that the tip is inside the block 1 container and is positioned at the top of it. With the specified z-index, it should be invisible until the user hovers over it and if I did that correctly, you should be able to see that in z-index7.html.