CSS positioning tutorial

The educational technology and digital learning wiki
Revision as of 17:44, 22 August 2016 by Daniel K. Schneider (talk | contribs) (Text replacement - "<pageby nominor="false" comments="false"/>" to "<!-- <pageby nominor="false" comments="false"/> -->")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
Learning goals
  • Understand CSS positioning features
  • Be able to create simple CSS-based layouts
Prerequisite
Concurrent
Moving on
Level and target population
  • Beginners
Teaching materials
  • See in the text
Remarks
  • This tutorial is intended for students in a field that is technology intensive (e.g. computer applications or educational technology). For people who need less, there exist many easy CSS tutorials on the web. This text is intended for students who also must learn principles and who are willing to learn CSS by doing a project, looking at CSS code and online reference manuals.
  • Ideally, a teacher also should assign a text formatting task, during or before assigning this tutorial for reading).
  • There are some inline examples. However, they had to be created in a away that makes them fit into a wiki page. I.e. we use inline style (something we usually don't advocate) and we also had to add extra styling properties.
  • Doing positioning with the "traditional" CSS2 box model is fairly painful. This is why there is a new standard called CSS Flexible Box Layout Module Level 1, W3C Candidate Recommendation, 5 January 2016. As of early 2016, most browsers do implement this, although it is not yet an official standards. Several prior versions with syntax and functionality changes exist. Be careful when looking at older tutorials !

Introduction - CSS positioning and the formatting model

Positioning and layout one of the more difficult CSS topics

  • The positioning model is quite complex with respect to how various properties interact
  • You also will have to fight browser implementation issues
  • See also CSS float tutorial (for creating simple layouts with float:left)

Positioning other than using floats is done with three sets properties:

  1. Four positioning properties: left, right, top and bottom.
  2. The position property will determine how these positions will be rendered (painted)
  3. The Z-index property will define the position in the "front/back" stack, i.e. define what is displayed on top of each other.

(1) The left, right, top, bottom properties

Each HTML element can be positioned with one of the left, right, top and bottom properties. Each of these properties defines a distance between this element and either the next element or the parent's border depending on the the position property settings.

CSS property/value example for positioning a box 1cm to the right and 1cm down:

 top: 1cm; 
 left: 1cm;

Example 1cm the left and 1cm up:

 right: 1cm;
 bottom: 1cm;

(2) The position property

The position property can take four values:

  • static (the default value, i.e. one elements follows another, either from left to right (or right to left) for inline elements, or down for block elements.
  • relative: The position a box will take if it is moved from its normal position.
  • absolute: The position a box will take with respect to its closest parent that does not have position:static. By default, this is the html element.
  • fixed: The position is defined with respect to the coordinates of the browser window, i.e. the so-called viewport.

Also, we suggest reading and playing with the The position declaration article at Quirksmode (probably the best web site about advanced CSS and browser compatibility)

(3) The Z-index

“In CSS 2.1, each box has a position in three dimensions. In addition to their horizontal and vertical positions, boxes lie along a "z-axis" and are formatted one on top of the other. Z-axis positions are particularly relevant when boxes overlap visually.” (CSS 2 spec, Layered presentation).

(4) The formatting model

Recall, that each HTML element is a box and that it may have boxes inside. According to the specification, “In CSS 2.1, many box positions and sizes are calculated with respect to the edges of a rectangular box called a containing block. In general, generated boxes act as containing blocks for descendant boxes; we say that a box "establishes" the containing block for its descendants. The phrase "a box's containing block" means "the containing block in which the box lives"”

Overall, the layout of boxes is governed by

  • The dimension of each box (content, padding, border and margin) and it's type (e.g. inline or block)
  • How it is positioned (normal, float, absolute, fixed)
  • How elements (boxes) are embedded within each other in the HTML.
  • External factors, such as the size of the browser window and embedded objects like pictures

Since these positioning concepts are fairly complex, we shall introduce them below through examples.

Basic positioning principles

In this section we discuss some of the above's principles using simple examples.

Absolute vs. relative positioning

Positioning is defined with respect some kind of coordinate system. I.e. if you tell un object to be at left=1cm and down= 1cm, you have to tell with respect to "what/where".

To do so, we need another property: position. The position property defines whether an element is positioned with respect to the parent element (absolute positioning) or with respect to its "normal" position (relative positioning).

Let's illustrate this with a few CSS examples:

  • Set the left edge of the element with respect to the left edge of the containing element:
div.picture {
     left:1cm;
     position:absolute;
     }
  • Set the left edge (and the whole element) with respect to its normal position.
div.picture2 {
     left:1cm;
     position:relative;
     }
  • Do not position, i.e. ignore the left (that's the default behavior of CSS)
div.picture3 {
    left:1cm;
    position:static;
     }

Below is screenshot of a complete example using id identifiers for the divs that we position. As you can see the first (yellow) div is not shown first. I will move 4cm to the right (i.e. left is 4cm). The second one (green picture 2) normally should then be positioned on top left, but it's moved 1cm to the right. The third one (red) will be to the left on line two, i.e. the line that follows the one taken by the first green one. The final one (green also), stays also on its line, but moves about 2cm to the right.

Absolute (yellow,red) and relative (green) positions

In the picture above, the green elements (picture 2 and picture 4) are positioned relative, the yellow (picture 1) is absolute, and red one is "normal", i.e. static. The (almost) complete HTML/CSS code for this not so interesting example looks like this:

<style type="text/css" media="all">

div#picture1 {
     left:4cm;
     width:2cm;
     position:absolute;
     background-color:yellow;
     }

div#picture2 {
     left:1cm;
     width:2cm;
     position:relative;
     background-color:green;
     }

div#picture3 {
    left:1cm;
    width:2cm;
    position:static;
    background-color:red;
     }
div#picture4 {
     left:2cm;
     width:2cm;
     position:relative;
     background-color:green;
     }
</style>
</head>

<body>
  <div id="picture1">picture 1</div>
  <div id="picture2">picture 2</div>
  <div id="picture3">picture 3</div>
  <div id="picture4">picture 4</div>
<div>

Let's move on a bit, because as you will learn, most of the time you would position a box with respect to some containing box, e.g. a div.

Absolute positioning will remove an element from the normal text flow, i.e. it will be inserted wherever you tell it to go. In other words, it can overlap with other elements. The following example and screenshot shows a possible effect of absolute positioning:

Absolution positions for three boxes

The HTML structure is very simple:

+------------------------+
|container               |
|   +--------------------+
|   +     some text      +
|   +--------------------+
|   |     id="left"      |
|   +--------------------+
|   |     id="right"     |
|   +--------------------+
|   |     id="random"    |
|   +--------------------+
+------------------------+


Most important HTML/CSS code:

  ....	
  <style type="text/css" media="all">
    #container {position:relative; height:3cm; border: 1px dotted}
    #left      {border:solid; position:absolute; left:1px; top:1px; width:auto;}
    #right     {border:solid; position:absolute; right:1px; width:auto;}
    #random    {border:solid; position:absolute; left:3cm; top:2cm; width:auto;}
  </style>
  ....
<div id="container">
  <div style="opacity: 0.3">

fill fill fill fill fill fill fill fill fill fill fill fill fill fill
fill fill fill fill fill fill fill fill fill fill fill fill fill fill
fill fill fill fill fill fill fill fill fill fill fill fill fill fill
fill fill fill fill fill fill fill fill fill

  </div>
  <span id="left">button left</span>
  <span id="right">button right</span>
  <span id="random">button random</span>
</div>

We are not done yet explaining basic principles. Layouting means understanding how various properties interact with respect to positioning coordinates. Read on ...

The position attribute in the parent box

Both position:relative and position:absolute CSS declarations in a parent box will have an impact on positioning of child elements. These declarations will define a so-called local coordinate system. Its child element's absolute positionings will refer to this box and not the page as a whole.

Let's now look at two very simples examples that should illustrate the principle:

The HTML structure (without showing the body) is the following:

+------------------------+
|div id="container"      | 
|   +--------------------+
|   | div id="left_col"  |
|   +--------------------+
|   | div id="right_col" |
|   +--------------------+
+------------------------+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
  <title>CSS background demo - First principles of instruction</title>
  <style type="text/css" media="all">
#container {
	   /* contents not relevant to position removed */
             }
#left_col  {
             border:solid thin; position:absolute; 
             top:0.5cm; left:0pt;  width:49%;
             }
#right_col {
             border:solid thin; position:absolute; 
             top:0.5cm; right:0pt; width:49%;
             }
  </style>
</head>

<body>
<div id="container">
  <div id="left_col">
  Contents of left column ....
  Contents of left column ....
  </div>

  <div id="right_col">
  Contents of right column ....
  </div>
</div>

</body>
</html>

This page shows will display like this:

2 columns positioned with respect to the page, not so good !

This example may not do what we want. Each of the two left_col and right_col boxes are positioned with respect to the body element, i.e. borders overlap. In order to position them with respect to the container element, we must use the code of the next example.

In the example below, the "container" element includes a position:relative; declaration. This is needed in order to create a relative positioning system for the child elements. Below are the important parts of the HTML/CSS code for another example

The HTML structure (without showing the body) is the following:

+------------------------+
|div id="top_right"      |
+------------------------+
|div id="container"      | 
|   +--------------------+
|   | div id="left_col"  |
|   +--------------------+
|   | div id="right_col" |
|   +--------------------+
+------------------------+
....
<style type="text/css" media="all">

#container {
             top:2cm;
             position:relative;
             border: dotted thin;
             color: #CCFF99;
             height:4cm;
             }
#top_right { 
             border:solid thin; position:absolute;
             right: 0;
             }
#left_col  {
             border:solid thin; position:absolute; 
             top:0.5cm; left:0pt;  width:49%;
             color: black;
             }
#right_col {
             border:solid thin; position:absolute; 
             top:0.5cm; right:0pt; width:49%;
             color: black;
             }
</style>
</head>

<body>
<div id="top_right">HOME</div>

<div id="container">
  container content that should be removed ...
  <div id="left_col">
  Contents of left column ....
  </div>

  <div id="right_col">
  Contents of right column ....
  </div>
</div>
.......
</body>
</html>

It should look like the this, although the layout somewhat adapts to the width of your browser window:

2 columns positioned with respect to a container "div" and a button, better

Life example:

In addition to this example, you also may look at the following one:

Some discussion:

  • As you can see, the left and right column boxes will move over the contents of the container box, i.e. absolute positioning removes a box from the normal "flow".
  • Also these two columns now position with respect to the container box, because the CSS of the container box includes the position:relative declaration. (We can't understand why the CSS folks didn't invite another keyword for creating a local coordinate system).
  • Finally, we added a little box on top right that is positioned with respect to the HTML page itself. As you can see, there is not default margin to its top and right.

Viewports

The viewport refers to what the user can see, i.e. the contents of the browser window.

Browsers can change the document's layout when a viewport is resized. In particular, all so-called "fluid" layouts do that. Also, as we shall see below, fixed positions are defined with respect to the viewport.

In addition, a user can zoom and that also will augment or reduce the size of the viewport. Zooming is very difficult to handle and can't be addressed here, since it requires JavaScript/DOM programming. For now, we just should mention that there is a difference between CSS pixels and screen pixels. When you zoom in to 200% a line with 1px width will show as 2px screen width, but as far as CSS is concerned, the line is still one CSS pixel. Finally, we should mention that position on mobile devices is difficult for now.

One relatively easy way to deal with small vs. large devices is to use so-called Media queries.

@media all and (max-width:440px) { .....}

Read more in Quirksmode's A tale of two viewports — part one and part two

The future CSS 3 Device Adaptation specification (working draft as of sept. 2011) addresses many of these issues. It “provides a way for an author to specify, in CSS, the size, zoom factor, and orientation of the viewport that is used as the base for the initial containing block.”

The Z-index

The z-index property can take three values:

  • auto: the default rules will apply (i.e. stack level is 0, no stacking context, first will be painted first)
  • integer: Higher means more important. You also can specify a negative number since the default display order is 0.

Z-index will apply to positioned elements.

Specifying a z-index property does two things:

  • It defines the stack level of the current box with respect to its "sister" elements
  • It creates a stacking context, i.e. all its child elements will be stacked with respect to each other.

Using the z-index can be a bit tricky because stacking interacts with positioned elements. In addition, the way IE implements it. By default, IE (all versions?) implements z-index values which it should not. According to the specification, within each stacking context, the following layers are painted in back-to-front order:

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants.
  4. the non-positioned floats.
  5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  7. the child stacking contexts with positive stack levels (least positive first).

This principle is applied recursively to to each stacking context. I.e. the browser starts rendering the top level elements according to the rules above and while doing so renders each of these again according these rules and so forth.

Examples:

#links_content {
    position:absolute;
    z-index: 1;
    }

#background_paintings {
    position:absolute;
    z-index: 0;
    }

Life example: landing-page-absolute-fixed-elements.html

Fixed positions

Fixed elements will display a box with respect to the viewport, i.e. the portion of the page that the user sees in the browser window, e.g. a picture could be positioned always 1% from the top and 1% from the left.

Fixed positions are often used to create floating menu bars and background images. This is shown in the following example.

#menu      { 
    position:fixed;
    z-index: 2;
    left: 1%;
    top: 2cm;
    border: solid thin; 
    width: 120px;
    }

Life examples:

To add later

(probably in a new page)

CSS menus

( ---- to expand ----)

The foundation of CSS pull out/pull down menus is:

  • Create a menu hierarchy with a ul > li > ul > li combo
  • Hide the ul elements that are within the li elements
  • Make them visible when the user hovers on the parent li
 li ul {display: none;} 
 li:hover > ul {display: block;} 

The major difficulty is coping with IE (as usual) and to a lesser degree with default margins.

Read:

CSS layouts with mostly absolute positioning

( ---- to do ----)

Example fixed layout that you could look at:

Fluid CSS layouts with some absolute positioning

Example fluid layout with sticking left/right menus:

Links

CSS 2 specification

CSS Positioning tutorials

Examples