Layout with CSS

Layout Using CSS

Using CSS to position elements in HTML pages is the modern approach to layout. Widespread adoption of CSS positioning in Web design took longer than it should have because the concepts are not as simple as using tables. The best thing you can do is experiment with example layouts to get a feel for how things work. It’s like learning to ride a bike—you may skin your knees a few times in the learning process, but you don’t forget once you learn.

Block-Level Elements and the Box Model

DIV is one of the dumbest labels you will see in CSS. Wherever you see the term div, immediately think box instead. A div is just a box!

Many elements in HTML create block-level elements—their presence defines a box. Boxes have specific properties relating to the rectangular box: borders, margins, padding. For cases where there isn’t a box defined by existing HTML elements, you can create boxes in CSS using the div tag. A div defines a box with no attributes initially, and you apply styling to the contents of the div box.

The Box Model

Normally, when you specify a width for a component, this does not include padding or borders. Some versions of Internet Explorer instead interpret the width as being the combination of the content, the padding, and the border.

An important distinction is often misunderstood by people: margins are not part of the element—they are assertions about the space around the element. Background colors and images only apply to the content, its padding, and its borders. Everything outside the border (i.e., the margin) is really more a property of the page than the element. If one element is placed above another, only the greater of the two touching margins is used—this is called a collapsing margin. Left and right margins do not collapse.

Block vs Inline Elements

When laying out a page, there are 2 kinds of HTML page elements.

  • Block elements: these HTML tags define rectangular boxes (see the Box Model). A block element always starts on a new line, aligned to the left, unless you explicitly specify a position. You can set the width, height, line-height, margins and padding for block elements. The default width of a block element is 100% of the containing element. HTML tags that define blocks are: div, h1-h6, p, table, form, blockquote, pre, ul, ol, dl
  • Inline elements: these always begin on the same line as the previous element, and wrap to the next line as they run out of room. You can’t change heights or margins for an inline element, and their width is only as long as the element (and can’t be changed). HTML tags that define inline elements are: a, br, img, span, iframe, strong, em.
  • You can change the default behavior of elements with the display property:
    • display:block will display that element as a block, even if it is considered inline
    • display:inline will force the element to be treated as an inline element
    • display:none will remove the element from the flow and the page, so the following items will collapse into the space

Normal Layout Flow

To lay out a page, the browser starts at the top of the HTML file, and starts flowing the block-level boxes down the left side of the page, starting from the top left corner. Every time a block-level element comes along, it starts on a new line. Unless you specifically say otherwise, this is the default rule for arranging boxes on a page. Only very simple layouts are feasible with the default model—a page is only a single stack of boxes. [figure 1] You can override the default behavior in several ways: by specifying the absolute position of elements, or by floating boxes to one side or the other. These are CSS properties, so they are applied to HTML elements in the same way as other CSS.

An important concept to understand is the flow for placing block elements on the page. In the normal flow, a new element is placed directly after the previous element. If the first element is 100 pixels tall, then the second block element will start 101 pixels down from the top, and along the left side. Block elements in the normal flow will never overlap.

Floating Elements

Floated RIGHT!

Floated elements are shifted within the normal flow (and are not in the flow), and the elements that follow it flow around the floated element, like water going around a rock in a river. The only choices are float:left and float:right. The floated element is shifted as far as possible in the specified direction—the side of the page if possible, or a previously-floated element if already there. Essentially, floats stack up towards the floated direction. If there isn’t room for a floated element on the line, then it "falls off" the line, and looks for the first available space in the flow. Floated elements must have a width specified (except images). Do not specify floating and positioning for the same object — use one method or the other, but not both. Floats make a handy way to create columnar designs. There are a number of bugs in Internet Explorer’s handling of floats, such as the infamous "peekaboo" disappearing text bug, finally fixed in IE7. The bugs are well-understood, though, and can be patched for IE. [diagram]

Floated LEFT!

If you don’t want elements to stack up after floats, you can specify that the element must clear left, right, or both-side floats before it by using the clear property (.e.g., clear:left, clear:right, clear:both). This forces a line break between the element and the previous float. Here is a great article about difficulties in using floats, including clearing floated elements.

An alternative to inserting a clearing element in the container after the floated elements is to use overflow:auto on the containing box.

Example 1: no overflow specified

Float 1.
Float 2.
Float 3.

Next element continues on same line....

Example 2: with overflow:auto on the outer container

Float 1.
Float 2.
Float 3.

Overflow:auto forces a break after the container just like the clear property.

Example 3: Box Height Collapses with Float

Fotofile Face Detection

This is the text.

 

Example 4: Box Height Collapse Fixed with Overflow:auto

Fotofile Face Detection

This is the text.

The Position Attribute

The primary way to alter the normal layout flow is to use the position attribute on a block-level element.

  • position:static: if you don’t otherwise specify a position, this is the default. The only time you might need to actually specify this is to override a different setting inherited from a parent; I have never actually used this in years of Web development. If all elements use the default static positioning, then the layout happens exactly as described above in the Normal Flow.
  • position:fixed: Puts an element at a fixed location in the browser viewport, regardless of scrolling. This allows you to keep your header or navbar at the same location on the screen, regardless of how the page gets scrolled. This completely removes the element from the flow, and it can overlap other items. This is poorly supported by Internet Explorer 6. I have avoided using this because of the poor browser support, although it can be hacked to work. IE before version 7 treats this like position:absolute, so the element will simply scroll with the page. All other modern browsers support this, so it is becoming feasible as a positioning technique.
    • There are usually other ways to achieve this affect, such as forcing scrollbars on inner DIVs to prevent the page itself from scrolling (using overflow:scroll).
    • You can also use frames to split the page, but this is universally frowned upon by the HTML community.
    • I have seen a jQuery-based "follower", which obviously relies on Javascript to do its work.
  • position:relative: there are 2 completely unrelated uses for position:relative, which is dumb. Relatively-positioned elements remain in the normal flow.
    • You can shift the position of the element relative to where it would have appeared in the normal flow (e.g., left:20px; top:20px; will shift the left edge 20px to the right, not place it at pixel 10; it will also shift the top down 20px) from where it would normally be positioned. This does not take the element out of the flow, but other boxes may overlap since they believe a relatively positioned box is at the unmodified position. This really isn’t used very much; the best use I’ve seen was to shift a drop shadow graphic from underneath the box it was embellishing.
    • The primary usage of position:relative is to establish a positioning context, so that child elements (things inside that box) can be positioned at exact locations inside the relatively-positioned box. Using position:relative creates a new instance of normal flow within the box.
    • You can use position:relative to both shift the box and establish a positioning context within it, but it’s unlikely.
  • position:absolute: placed an element at fixed coordinates inside the containing box. Absolutely-positioned elements are taken out of the flow entirely, so normally-positioned boxes don’t even “see” the absolutely-positioned elements. Subsequent content will flow into the space, so elements will overlap the absolutely-positioned elements unless you use margins or a z-index value to control the stacking.
    • Absolute positioning can be very beneficial inside other boxes, since absolute positioning is based on the containing element. For a top-level element, the containing element is the entire page. If you put an absolutely-positioned element inside any positioned element, however, the coordinates are based on the top-left corner of the container, starting at zero for the x- and y-values. Effectively, absolute coordinates are truly relative—another brain-dead use of nomenclature in CSS.
    • Use the CSS properties top, bottom, left, and right to specify locations. These can even be stated as percentages, which means the "absolute" position changes depending on the width of the browser window. You normally specify one of top/bottom and one of left/right, but you can specify both top and bottom or left and right at the same time if needed.
    • If your item is at the top level (not inside anything except the BODY tag), then you do not need to establish a positioning context of relative with the containing object. Absolutely-positioned elements at the top level are placed relative to the upper-left corner of the browser window.
    • The biggest problem with absolutely-positioned elements is that they can overrun other elements easily, especially at the bottom. There is no way to position an element after an absolutely-positioned element, since it is out of the flow.

Stacking Order and Z-index

Sometimes, you want elements to overlap. The CSS property z-index applied to a block-level element determines the stacking order when elements overlap. A higher z-index is stacked on top of a lower z-index. This can be complicated by parent-child relationships: the parent’s z-index determines where the entire container is displayed, and a z-index applied to children just determine where they are layered inside the container. Effectively, a child cannot have a higher z-index than its parent container. Z-index only works on positioned elements, and you can use both positive and negative numbers for the value.

Examples of CSS-Based Layouts

  • 1a: Example page before positioning applied: using 5 colored DIVs to demonstrate positioning in the Normal Flow. Because they are block-level elements, each successive box (div) starts on a new line after the previous box.
  • 1b: Fixed-width page, centered in browser window:
    • body {text-align:center}
    • #content {text-align:left; width:600px; margin: 0 auto;} : this needs to wrap around everything inside the body tag. The standard way to center something is to set the left and right margins to auto. Internet Explorer misinterprets this, but you can center in IE with text-align:center in the body, something else it misinterprets. The side-effect is that all text is centered, so you must explicitly override this. The CIS86 Web site uses this technique to center the contents.
  • 2a: Using position:relative to offset the position of a box. This is an uncommon usage because the rest of the page acts as if the box was at the unpositioned location.
    • position:relative; left:20px; top:20px; is used to shift DIV Two, although the following boxes are placed as if DIV Two is in its normal location.
  • 2b: Absolute Positions inside a Relatively placed DIV : by setting position:relative on a block element, you can then use absolute positioning within that block. Elements can overlap inside the box.
  • 3a: Three Columns #1 (the so-called Holy Grail of HTML coding: robust 3-column layout)
  • 3b: Three Columns #2
    • L is float:left, width:10%;
    • R is float:right; width:10%;
    • Center is 100%.
  • 3c: Three Columns #3 : floated interior columns.
    • Outer DIV has fixed width.
    • Each interior box is: float:left; width:33%.
    • I used the first example, the centered 800-pixel wide layout, as the basis for this. I left DIV 1 as the header, and DIV 5 as the footer. I added a wrapper called "outerbox" around DIVs 2, 3, and 4, and then floated the 3 boxes inside outerbox.
  • 4a: 2 Columns #1 : absolutely-positioned interior columns
  • 4b: 2 Columns #2 : interior columns are floated left and right.
    • L,R are width:50%. Floated left and right instead of using absolute positions. This is very error-prone, since IE handles the "stepdown" effect differently than other browsers.
  • 5: DFF’s ImageBox: this uses float:left for the boxes. Look at this with View Source Chart and View Source.

There are quite a few more complex examples of positioning in the Examples section of the class Web site.

CIS86 HomeContact DFFSiteMap • © 2009, Dennis F. Freeze