Controlling Presentation with Measurement and Location Properties in Quirks Mode

Dynamic HTML (DHTML) exposes measurement and location properties that you can use to change the size and position of HTML elements on your Web pages. When you understand what these properties are and how they affect elements on a page, you can achieve greater control over the appearance of your Web pages. For example, you can use these properties to design pages that are similar to documents in other applications, such as Microsoft PowerPoint or Microsoft Word. This article includes the following sections, which explain how to use measurement and location properties to control the appearance of a Web page.

Note  This document describes the layout and positioning properties of a page rendered in Windows Internet Explorer's Quirks mode. You do not need to define a !DOCTYPE for the examples on this page to function properly. For layout and positioning information under the strict rendering mode, please view Controlling Presentation with Measurement and Location Properties In Strict Mode .

Requirements

This documentation assumes that you are familiar with a client-side scripting language, such as Microsoft JScript or Microsoft Visual Basic Scripting Edition (VBScript). You should also be familiar with the DHTML Document Object Model (DOM) and Cascading Style Sheets (CSS).

Layout Fundamentals

Measurement and location properties are available through the DHTML Document Object Model (DOM) and as CSS attributes. You can use DHTML DOM properties to programmatically set CSS attributes. Properties exposed through the DHTML DOM return values based on how an element renders in the document. CSS attributes return values based on the preset values of other CSS attributes.

All CSS properties are exposed through the style and the runtimeStyle objects. You can use the currentStyle object to query the current value of a property.

The Element Rectangle

Every visible element on a Web page occupies an absolute amount of space in the document. The amount of space occupied by an element is defined by the element rectangle or box. An element rectangle includes all of the layout and display properties plus any content.

In the preceding graphic, the margin, border, and padding properties are shown surrounding the content of a generic element. "Element Width" represents the width of the element's content, and "Box Width" represents the width of the content plus the additional space occupied by the layout properties. The height of an element and its layout properties can be represented similarly.

Block Versus Inline Elements

All visible HTML Elements are either displayed in blocks or inline. A block element, such as a div, typically starts a new line and is sized according to the width of the parent container. An inline element, such as a span, typically does not start a new line and is sized according to the height and width of its own content.

Size, Layout, and Location of Elements

An element has layout when one of the following conditions is true:

  • It has a width and/or a height specified
  • It is an inline-block (display: inline-block)
  • It has absolute positioning (position: absolute)
  • It is a float (float: left, float: right)
  • It is a table element
  • It is transformed (style="zoom: 1")

Nearly all inline and block elements have layout. The exception is an inline element that is neither positioned nor has its height or width specified.

A positioned element has specific measurements and can be set to a location using the CSS layout attributes: top, right, left, bottom. The location of non-positioned elements are relative to their nearest ancestor with layout (offsetParent). Location is useful when moving one or more elements to relative or absolute coordinates within the document. It can also be useful for creating specific document styles.

Measurement Fundamentals

Height and width are the measurements used most frequently. Use the offsetHeight and offsetWidth properties to retrieve these measurements from any rendered inline or block element. To set these measurements, use the height and width attributes (or related properties). For a CSS measurement attribute to be useful, you must set the attribute's value before retrieving it.

Inline elements gain layout when the height or width are set. Inline elements with layout expose the same layout properties, such as border, margin, and padding, as block elements. The following example shows how layout attributes affect the appearance of a web page when the height attribute is set on an element.


<!-- Styles render because this link has layout. -->
<a href="http://msdn.microsoft.com/"
   style="width:150px; border:1px solid; padding:10px; margin:5px;">
   MSDN Online</a>

<!-- Styles do not render because this link has no layout. -->
<a href="http://msdn.microsoft.com/"
   style="border:1 solid; padding:10px; margin:5px;">
   MSDN Online</a>

Absolute and Relative Length Units

When setting or retrieving an element's measurement and location values, you can use different length units to achieve a particular style. Using length units consistently simplifies measurement and location values. The mixing of length units requires you to determine the value of an absolute length unit programmatically, based on a relative unit for every system. For example, you would have to convert inches to pixels on every machine that renders your document.

Layout properties contribute to the dimensions of an element and should be considered when determining the dimensions of the content. The content of an element is sized to any specified measurements minus the border and padding measurements. Because the DHTML and CSS properties do not provide a measurement of the content without its padding, the padding properties must be specifically queried to retrieve an accurate measurement. While you can use the offset and client properties to determine the size of the content, it is easier to subtract the size of the border and padding properties from the width of the element.

Consider the following div element:


<div id="oDiv"
   style="padding:10px; width:250px; height:250px;
      border:2px outset; background-color:#CFCFCF;">
</div>

The specified height and width of the preceding div is 250 pixels. You can formulate the width of the content as follows:


oDiv.style.width - oDiv.style.borderWidth - oDiv.style.padding

However, since all three properties return variant data types, you must either convert the values to integers or use properties that return integer values. For example, to obtain the width of the element in pixels, you can use one of the following techniques in JScript:


var iWidth = oDiv.style.pixelWidth


var iWidth = parseInt(oDiv.style.width) (width is specified in pixels)


var iWidth = oDiv.offsetWidth

If the values of the border and padding properties are set in the same length units as the width property, you can convert the variant value to an integer. To determine the content dimensions, use the border and padding properties, or the client and padding properties, and the element dimensions. When retrieving border and padding values, use the borderWidth and padding properties, if the values are uniform on all sides of the element. Otherwise, you must specifically query the borderLeftWidth, borderRightWidth, paddingLeft, and paddingRight properties to obtain an accurate measurement.

For example, to obtain the width of the content in pixels, you can use one of the following techniques in JScript, where iWidth is based on one of the previous example techniques.

  • Use this formula if the border and padding sizes are not uniform on all sides.
    
    var iCntWidth = (iWidth - parseInt(oDiv.style.borderLeftWidth) 
        - parseInt(oDiv.style.borderRightWidth) 
        - parseInt(oDiv.style.paddingLeft) 
        - parseInt(oDiv.style.paddingRight)
        )
    
    
  • Use this formula if the border and padding sizes are uniform on all sides.
    
    var iCntWidth = (iWidth - parseInt(oDiv.style.borderWidth) 
        - parseInt(oDiv.style.padding)
        )
    
    
  • Use this formula instead of using the border properties.
    
    var iCntWidth = (iWidth - (oDiv.offsetWidth - oDiv.clientWidth) 
        - parseInt(oDiv.style.padding)
        )
    
    
Note  These formulas will not work if padding or margin are specified using percentages.

Measurement Example

The following example uses the first formula from the preceding section to move and resize a positioned element based on the content of another element.


<script>
window.onload=fnInit;
function fnInit(){
   var iWidth=oDiv.style.pixelWidth;
   var iHeight=oDiv.style.pixelHeight;
   var iCntWidth=(iWidth - parseInt(oDiv.style.borderLeftWidth)
      - parseInt(oDiv.style.borderRightWidth)
      - parseInt(oDiv.style.paddingLeft)
      - parseInt(oDiv.style.paddingRight));
   var iCntHeight=(iHeight - parseInt(oDiv.style.borderTopWidth)
      - parseInt(oDiv.style.borderBottomWidth)
      - parseInt(oDiv.style.paddingTop)
      - parseInt(oDiv.style.paddingBottom));
   var iTop=oDiv.offsetTop + parseInt(oDiv.style.borderTop)
      + parseInt(oDiv.style.paddingTop);
   var iLeft=oDiv.offsetLeft + parseInt(oDiv.style.borderLeft)
      + parseInt(oDiv.style.paddingLeft);   
   oDiv2.style.width=iCntWidth;
   oDiv2.style.height=iCntHeight;
   oDiv2.style.top=iTop;
   oDiv2.style.left=iLeft;
}
</script>
<div id="oDiv"
   style="padding:20px 5px 10px 10px; width:250px; height:250px;
      border:10px outset; background-color:#CFCFCF;">
</div>
<div id="oDiv2" style="position:absolute; border:2 inset;
   background-color:#000099;">
</div>

Location Fundamentals

The portion of Internet Explorer that displays the document is referred to as the client area. Beginning in the top left corner with x and y coordinates set at 0, the client area has no inherent margin or padding. The BODY element is the first container in the document and is the top-most parent. Like the client area, the BODY has no default margin or padding, and also begins at x and y coordinates of 0.

The distance between the element and its positioned or offsetParent defines the element location. Internet Explorer exposes the element location when the document renders or when a change to the content forces the document to redraw. Understanding how elements are located within the document is key to determining and changing the location of an element.

The general layout of elements is primarely based on document flow. Document flow is analogous to the writingMode attribute. In Western languages flow indicates the layout of content from left to right, top to bottom. Inline and block elements that do not have absolute positioning flow in this manner by default; unless otherwise specified. Elements having absolute positioning render outside of the document flow. The document flow is the order of the elements after their measurements are calculated. Changing the measurements or location of positioned elements does not affect adjacent elements in the document flow, but it might affect child elements.

Non-positioned inline and block elements render together and are part of the document flow. An element's location can change when the measurement of another element appearing earlier in the document flow changes. The measurement of an element changes when the content, layout, or font style of another element is updated after the document renders. Changing the measurements of a non-positioned element changes the location of adjacent elements in the document flow. .

Top and Left Locations

The following example shows how to retrieve the location of an inline element and how the measurement of another element affects the location of that element.


<script>
function getLocation(){
   alert("Left: " + oSpan.offsetLeft);
   oSpan1.innerHTML="Changed content.";
   alert("Left: " + oSpan.offsetLeft);
   oSpan1.innerHTML="This is some dynamic content.";
}
</script>
</body>
<span id="oSpan1">This is some dynamic content.</span>
<span style="background-color:#CFCFCF;" id="oSpan">
This content won't change, but this element's location will change.
</span>
<input type="button" VALUE="Locate Second Element" onclick="getLocation()">
</body>

Offset Parents

Although you can retrieve the top or left location of any element that renders, the values of these locations are relative to the positioned or offsetParent. You cannot always rely on a single value when determining the distance between two elements.

The following image depicts the offsetLeft values of a span element and a table element. The offset value for both elements is 50 pixels. However, if you query the offset value of a table cell, the offsetLeft property returns only 3 pixels, because table is the offsetParent of the td element (Cell 1). To determine the distance from the table cell to the edge of the screen, add the two values together.

Offset left values of a span element and a table element

Special Cases

Certain elements, such as the table element, expose their own object model and a specific set of properties, such as the cellPadding property and the cellSpacing property. From the currentStyle object, you can retrieve the current value of the cellPadding property through the padding property. You must retrieve the cellSpacing property directly from the table element.

Nested Elements

Determining the distance between any nested element and its offsetParent, such as the BODY element, might require you to include the location of the offsetParent. For example, the top and left locations of a td element return the distance between the cell and the offsetParent, which is the table element. To determine the distance between a nested element and the BODY element, you must walk up the document hierarchy and add the left location values of all the offsetParents between the two elements.

Location Example

The following example shows how to programmatically retrieve the absolute distance between a td element and the BODY element.


<script>
function getAbsoluteLeft(oNode){
   var oCurrentNode=oNode;
   var iLeft=0;
   while(oCurrentNode.tagName!="BODY"){
      iLeft+=oCurrentNode.offsetLeft;
      oCurrentNode=oCurrentNode.offsetParent;
   }
   alert("Left: " + oNode.offsetLeft + "\nAbsolute Left: " + iLeft);
}
</script>
<body>
<input
   type="button"
   value="Get Absolute Left"
   onclick="getAbsoluteLeft(oCell)"/>
<table cellspacing="2">
<tr><td id="oCell">Cell 1</td></tr>
</table>
</body>

Positioned Elements

The measurements of an element with absolute positioning are first defined by any specified measurement properties, such as height or width, followed by its content. This is true for block and inline elements. However, a relatively positioned element retains its block or inline measurements unless otherwise specified.

The following example shows that the measurements of a block element and an inline element are the same when the position attribute is set to absolute.


<div style="background-color:#CFCFCF; position:relative; top:10px;">
   Text
</div>
<span style="background-color:#CFCFCF; position:absolute; top:30px;">
   Text
</span>

You can use the same procedure to set or retrieve the measurements of positioned elements and non-positioned elements.

How to Use Measurement and Location Properties

Measurement and location values do not have to be static integers. They can be scripted values based on distances and dimensions of other elements, expressed lengths (as in more traditional media) or equations. When working with several elements, you can use the measurement of one element to set the location of another.

You can use the measurement and location properties discussed in this overview to construct more complex creations. For example, to center an element within its container, set its left coordinate to the sum of one-half the width of its container minus one-half the width of the element. The syntax is demonstrated in the following example.


<script>
function center(oNode){
   var oParent=oNode.parentElement;
   oNode.style.left=oParent.offsetWidth/2 - oNode.offsetWidth/2;
}
</script>
<div
   id="oDiv"
   onclick="center(this)"
   style="position:absolute;">
   Click Here To Center
</div>

Expressions are formula-derived values. You can use expressions to continually update property values . In the preceding example, the element is centered once, but does not remain centered if the browser window is resized. To preserve a particular layout, use a formula rather than a static value.

Use the setExpression method to add expressions to CSS attributes and DHTML properties. The following example shows how to center an element using an expression rather than a static value.


<script>
function center(oNode){
   oNode.style.setExpression("left","getCenter(this)");
}
function getCenter(oNode){
   var oParent=oNode.parentElement;
   return (oParent.offsetWidth/2 - oNode.offsetWidth/2);
}
</script>
<div
   id="oDiv"
   onclick="center(this)"
   style="position:absolute;">
   Click Here To Center
</div>

While the DHTML DOM provides an easy way to obtain the current dimensions and location of an element, you must use CSS to set these values in most cases. Except for elements that expose height and width properties, such as img and table, you can use various CSS attributes to set the size of an element. While many properties return values in pixels, you can use some CSS properties with specific length units, such as inches or centimeters.

For example, if an h1 element has top and left positions of 2 inches, the offsetTop and offsetLeft properties return approximately 190 pixels, depending on the screen resolution. Since the top and left properties return a string value of 1in, you can use the posTop and posLeft properties to increment or decrement the location in inches rather than pixels. The posTop and posLeft properties use the same length units as their counterpart CSS properties, top and left.

The following example moves the h1 element 1 inch every time the user clicks the element.


<script>
function moveMe(){
   // Move the object by one inch.
   oHeader.style.posLeft+=1;
   oHeader.style.posTop+=1;
}
</script>
<h1 id="oHeader"
   style="position:absolute; top:1in; left:1in;"
   onclick="moveMe()">
   Header
</h1>

When moving elements to specific locations in a document, it is sometimes necessary to account for the different properties of the box element. Height and width values include border and padding measurements. Moving one element to the visible corner of another element is relatively easy using the offset properties and techniques described in the preceding example. However, when positioning an element at a specific point in the content of another positioned element, you must include the size of the padding and border. You can use either the client properties or the padding and border properties to establish a location within the content of an element. You can also use a TextRectangle to establish a location.

The following example shows three different ways to position an element within the content of another element. First, CSS pixel, border, and padding properties are used to move an element to the content within a positioned element. Next, DHTML offset and client properties are used to move an element within the content of a positioned element without accounting for the padding. And finally, a TextRectangle is used to establish the position of the element.


<script>
function fnMove1(){
   // Method 1: Use only CSS properties
   var iTop1=oDiv.style.pixelTop +
      parseInt(oDiv.style.borderTopWidth) + 
      parseInt(oDiv.style.paddingTop);
   var iLeft1=oDiv.style.pixelLeft + 
      parseInt(oDiv.style.borderLeftWidth) + 
      parseInt(oDiv.style.paddingLeft);
   oMarker.style.top=iTop1;
   oMarker.style.left=iLeft1;
}
function fnMove2(){
   // Method 2: Use DHTML properties.
   var iTop2=oDiv.offsetTop + oDiv.clientTop;
   var iLeft2=oDiv.offsetLeft + oDiv.clientLeft;
   oMarker.style.top=iTop2;
   oMarker.style.left=iLeft2;
}
function fnMove3(){
   // Method 3: Use DHTML, CSS, and a TextRectangle.
   var aRects=oDiv.getClientRects();
   var oRect=aRects[0];
   var oBnd=oDiv.getBoundingClientRect();
   oMarker.style.top=oBnd.top + 
      parseInt(oDiv.style.paddingTop) + 
      parseInt(oDiv.style.borderTop);
   oMarker.style.left=oBnd.left + 
      parseInt(oDiv.style.paddingLeft) + 
      parseInt(oDiv.style.borderLeft);;   
}
</script>


<div id="oDiv"
   style="position:absolute; top:150px; left:50px; border:10px outset; 
      padding:10px; width:250px; height:250px; background-color:#EFEFEF;">

Move marker here.
</div>


<span id="oMarker"
   style="top:200px; left:200px; position:absolute;
      border: 2px outset; background-color:#CFCFCF;">
      
Marker
</span>


<input type="button" value="CSS" onclick="fnMove1()">
<input type="button" value="DHTML" onclick="fnMove2()">
<input type="button" value="TextRectangle" onclick="fnMove3()">

Advanced Techniques

You can use DHTML expressions and the runtimeStyle and currentStyle objects to create more advanced measurement and location formulas. Expressions use formulas to return a possible value for any DHTML or CSS read/write property. To query the current value of a property, use the currentStyle object instead of the style object. To temporarily set a property value, use the runtimeStyle object instead of the style object. When a property value is cleared from the runtimeStyle object, the value reverts to the original property value set on the style object.

Expressions, DHTML, and CSS provide a robust model for delivering information to your audience. The following example uses these technologies to animate a list when the document loads. The marginLeft attribute includes an expression that returns a value based on a variable.

Once the document loads, the setInterval method is invoked to increment the variable until it reaches a target value. The amount is determined by the marginLeft property of a particular list item's sibling, available from the previousSibling property. When the variable increments, the recalc method is invoked with the true parameter, because the marginLeft attribute is not implicitly dependent on the variable. Adding the marginLeft value of the sibling list item causes the entire list to cascade.


<style>
li {margin: expression(fnTabIt(this));}
</style>
<script>
window.onload=fnInit;
// Starting marginLeft increment.
var iDML=0;
// Target marginLeft increment.
var iDMLTarg=30;
// Increment modifier.
var iDMLMod=.25;
// Animation speed in milliseconds.
var iDMLSpeed=50;
var oInterval;
function fnTabIt(oNode){
   var oPSib=oNode.previousSibling;
   if(oPSib!=null){
      var iML=0;
      if(oPSib.style.marginLeft!=""){
         iML=parseInt(oPSib.style.marginLeft);
      }
      return ((iDML*iDMLMod) + iML);
   }
   else{
      return 0;
   }
}
function fnAdjustTab(){
   if(iDML<iDMLTarg){
      iDML++;
      document.recalc(true);
   }
   else{
      iDML=iDMLTarg;
      window.clearInterval(oInterval);
   }
}
function fnInit(){
   oInterval=window.setInterval("fnAdjustTab()",iDMLSpeed);      
}
</script>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
</ul>

Click the following Show Me button for an interactive demonstration of the measurement and location properties. When you select a pair of properties, the dimensions and distances are displayed using indicators created with the same techniques discussed in this overview.

Click to view sample.

Related topics

CSS Overviews and Tutorials
About the DHTML Object Model
About the W3C Document Object Model
About Dynamic Properties
About Element Positioning
Alphabetical Index (CSS)
DHTML Reference
hasLayout

 

 

Show: