Normal Flow and Positioning - UI Core Concepts - Developing Web Components (2015)

Developing Web Components (2015)

Part I. UI Core Concepts

Chapter 3. Normal Flow and Positioning

Jason Strimpel

Every web component will be appended to the DOM and ultimately rendered to the screen for users to interact with. Understanding where and how an element, the building block of a web component, is positioned is key to developing web components.

Not understanding fundamental layout concepts can have a great impact on your web component’s design and implementation. For instance, depending on the requirements, a modal dialog can be rendered by calculating its size relative to the viewport and positioning it absolutely, or a simpler technique using fixed positioning and margins can be utilized. The latter technique uses pure CSS to do the positioning, so it performs much better, and the likelihood of bugs is decreased because you are doing significantly less DOM manipulation via JavaScript.

The two key concepts for understanding how the browser lays out a page are normal flow and positioning.

Normal Flow

The browser renders elements by placing them on a page according to what is known as normal flow.

Per the W3C CSS 2.1 specification:

Boxes in the normal flow belong to a formatting context, which may be block or inline, but not both simultaneously. Block-level boxes participate in a block formatting context. Inline-level boxes participate in an inline formatting context.

Let’s translate this W3C-speak into something someone other than a browser developer can understand.

“Boxes” refers to the box model, which describes how boxes represent elements. Every element on the page is a box composed of pixels. Boxes have properties such as padding, margins, and borders that, combined with the box content, determine how much space an element will occupy on a page. There are other properties, like box-sizing and the document type (in older versions of Internet Explorer), that can impact how these rules are interpreted and the resulting space occupied, but for the most part it a very simple model.

Block elements flow vertically (stacked one on top of the other) and fill their parent container if a width is not set. Inline elements flow horizontally (side by side) and occupy only as much width as the box context, left and right margins, and padding require. Figure 3-1 illustrates the difference. Setting the width and height on an inline element does not have any effect on the space it occupies.

inline and block element example

Figure 3-1. An inline element occupies only as much width as its content requires, while a block element occupies the full width of its containing element unless a specific width value is set

This is how elements normally flow within a document, if specific position values are not applied.

Positioning Elements

In the normal flow, an element’s default position value is static. A static element is technically not positioned. A positioned element is said to have a position value of relative, absolute, or fixed, and it is removed from the normal flow:

<!-- not positioned -->

<div>Some amazing text</div>

<!-- positioned -->

<div style="position: relative">Some amazing text</div>


Positioning does not cascade (i.e., it is not inherited by child elements), so you have to specifically set it on an element. Otherwise, the default value of static will be applied.


When an element is positioned, it is considered to be a containing element. A containing element is a reference point for positioning child elements using the top, right, bottom, and/or left properties. This containing element then becomes the offsetParent for its child elements and any ancestors of the children that are not descendants of closer-positioned ancestors. Figure 3-2 illustrates the effects of different position values.

position elements example

Figure 3-2. A relative-positioned containing element with a static element and an absolute-positioned element that has top and left values of 40px

How the browser determines an element’s offsetParent

An element’s offsetParent property can be either null, the <body>, or an ancestor element other than the <body>. The browser uses the W3C specification to determine an element’s offsetParent value, as follows:

offsetParent is null

Occasionally, an element’s offsetParent value will be null. This occurs when the element is the <body>, when the element does not have a layout box (i.e., its display is none) and when the element has not been appended to the DOM. The offsetParent will also be null if the element’s position is fixed because it is positioned relative to the viewport, not another element. The following example illustrates these cases:

<div id="div1" style="display: none"></div>

<div id="div2" style="position: fixed"></div>

var $body = $('body');

console.log($body.offsetParent()[0]); // logs <html>

console.log($body[0].offsetParent); // logs null

var $div1 = $('#div1');

console.log($div1.offsetParent()[0]); // logs <html>

console.log($div1[0].offsetParent); // logs null

var $div2 = $('#div2');

console.log($div2.offsetParent()[0]); // logs <html>

console.log($div2[0].offsetParent); // logs null


While the value of offsetParent can be null, the return value from jQuery’s offsetParent method is never null. jQuery returns <html> as the offsetParent, ensuring that there is always an element against which to operate.

offsetParent is <body>

If the element is not a descendant of a positioned element and it does not meet any of the null criteria, then its offsetParent will be the <body>.

offsetParent is an ancestor element other than <body>

If the element is a descendant of a positioned element, then the closest positioned ancestor will be its offsetParent. If an element is not a descendant of a positioned element but is a descendant of <td>, <th>, or <table>, then its offsetParent will be the closest of the aforementioned tags.


Positioning is frequently misunderstood. Often developers will set a different position value on an element in an attempt to fix a layout when things are not looking quite right. While this approach can “fix” a layout, it does not promote an understanding of how positioning actually works. Having a firm grasp of positioning can save you a great deal of time in the long run, because once you understand how it works you will begin to construct pages in a much more efficient manner.

Relative positioning

When an element is positioned relatively, the space it would have occupied in the normal flow is reserved. All other elements in the normal flow render around the space as if the element were in the normal flow. Visually, it is placed as if its position value were static. However, asFigure 3-3 illustrates, unlike with a static element, setting the top, right, bottom, or left values will shift the element accordingly. Positioning an element relatively is typically done to create a containing element for positioning child elements, or to apply a z-index (z-index is not applicable to statically positioned elements). Relative positioning is assigned as follows:

.some-class-selector {

position: relative;



Think of relative as being relative to the element and the space it occupies in the normal flow.

relatively position element with top and left values of 10px

Figure 3-3. A relatively positioned element with top and left values of 10px—note that the space it would have occupied in the normal flow remains intact

Absolute positioning

When an element is positioned absolutely, it is taken out of the normal flow of the document and the space the element would have occupied collapses (see Figure 3-4). The element can then be positioned by setting the top, right, bottom, and left values. Absolute positioning is useful for creating components such as tooltips, overlays, or anything that should be positioned at a precise location outside of the normal flow.

absolutely positioned element with an opacity of 0.75, and top and left values of 75px

Figure 3-4. An absolutely positioned element with an opacity of 0.75 and top and left values of 75px—note that the space it would have occupied in the normal flow collapses

Fixed positioning

An element is also taken out of the normal flow of the document when its position is fixed. It is positioned relative to the viewport, not the document, so when the page is scrolled the element remains fixed in place as if it were part of the viewport itself. This is useful for creating sticky headers and footers, and modal overlays. Here’s an example:


Covers the viewport when applied to an

element that is a child of the <body>.

It stretches the element across the <body> by

fixing its position and setting all the position

properties to 0. This makes it impossible to

interact with any elements that are in lower rendering



.modal-overlay {

position: fixed;

top: 0;

left: 0;

right: 0;

bottom: 0;

background: #000;

opacity: .5;



Centers an element in the viewport by setting the top and left

properties to 50%. It then accounts for the height and width of the element

by taking half the height and width, and sets the top and left properties

respectively by negating these values.


.modal-content {

position: fixed;



margin-top: -100px;

margin-left: -200px;

width: 400px;

height: 200px;

background: #fff;

padding: 10px;

overflow: auto;


<div class="modal-overlay"></div>

<div class="modal-content">I am the modal content. Fear me.</div>

Calculating an Element’s Position

In addition to understanding positioning, it is important to know how to get an element’s position relative to the viewport and the document. This is useful for positioning elements relative to each other when creating components such as tooltips, dialogs, sliders, etc.

Relative to the Viewport

Getting an element’s position relative to the viewport alone is typically not that useful. Most of the time you want the element’s position relative to the document, so you can absolutely position another element next to it.

However, the method used to retrieve the position relative to the viewport, element.getBoundingClientRect, returns the top, right, bottom, and left values, which allows you to easily calculate an element’s width and height. This information, in conjunction with an element’s position relative to the document, is useful when creating components that need to align with another element or be constrained by another element’s size, such as drop-downs or tooltips.

Alternatively, you could just use $.outerWidth and $.outerHeight to obtain an element’s dimensions, but element.getBoundingClientRect is significantly faster. Also, element.getBoundingClientRect can be used with a couple of other properties to quickly look up an element’s position relative to the document:





<input name="fname" />





var $input = $('[name="fname"]');

var rect = $input[0].getBoundingClientRect();

Relative to the Document

Getting an element’s position relative to the document is useful for absolutely positioning an element so that it remains positioned as the page scrolls, and for positioning elements relative to each other within the document. It is a fairly straightforward process. You traverse the DOM, finding each offsetParent, and get its offsetLeft and offsetTop. These values are the offset from the next offsetParent, so you have to sum the values until you reach the <body>:

function getElOffsets(el) {

var offsets = {

left: el.offsetLeft || 0,

top: el.offsetTop || 0


// loop through ancestors while ancestor is an offsetParent

while (el = el.offsetParent) {

// sum the offset values

offsets.left += el.offsetLeft || 0; += el.offsetTop || 0;


return offsets;


A quick Internet search for “JavaScript get element position relative to the body” will result in numerous examples that are roughly the same as the one outlined here. However, there is a much better way of doing this in conjunction with element.getBoundingClientRect, courtesy of jQuery:


// box is the el.getBoundingClientRect()

// win is the window object

// docElem is <html> (see



// calculating left and top return values

// 1. get the distance of top or bottom from the viewport

// 2. get the distance between the viewport top or left from the top of the page

// & add it to the value from distance of top or bottom from the viewport

// 3. subtract any top or left offsets of <html>, e.g., margins

offset: function( options ) {


return {

top: + win.pageYOffset - docElem.clientTop,

left: box.left + win.pageXOffset - docElem.clientLeft



I recommend just using $.offset as it performs consistently across browsers, and jQuery has been well tested and vetted by a very large user community. $.offset is an excellent example of the benefits of using a DOM manipulation library: you get the collective intelligence of a community wrapped up in a nice API.

Positioning the Dialog Widget

The dialog widget will need to be absolutely positioned, so that it can be removed from the normal flow and not impact the page’s layout. Ignoring all other factors, such as the dialog element’s location in the DOM tree, this is very easy to accomplish:

function Dialog (options) {

// call superclass constructor, options);

return this;


Dialog.prototype.init = function (options) {

// call super method, options);

// position the dialog's root element absolutely

this.$el.css({ position: 'absolute' });



In this chapter we examined the importance of understanding normal flow and positioning, and specifically how having a firm understanding of these concepts can significantly improve the design and performance of a component (e.g., using JavaScript versus pure CSS to position a dialog). As part of this examination we reviewed the box model and the two main types of boxes, block and inline. Next we covered the different types of positioning: relative, absolute, and fixed. After that we discussed how the browser positions an element and how to determine a positioned element’s offsetParent. Finally, we applied this knowledge to the dialog widget.