eFORCE
Blogs Home | Corporate Website

CSS Scripting Layout Specification

 
CSS Scripting Layout Model
Table of Contents
Abstract   top
This document describes a new set of CSS properties and object specifications that together compose a more powerful means to describe complex arbitrary layout criteria that are reusable and extensible. The new properties are ECMAScript (JavaScript) expressions that are encapsulated in a construct as a layout policy. A layout policy is referenced in CSS rules. The expressions composing a layout policy are woven together virtually in a constraint resolving system to perform a specified layout. New object specifications and a set of global objects defined in the constraint resolution script runtime environment enable powerful operations to be expressed succinctly resulting in more readable and compact layout specifications.
Introduction   top
Many in the web development community are dissatisfied with the layout capabilities in the current CSS standard and often resort to various client-side JavaScript solutions to fulfill their layout needs. There are several proposals before the W3C CSS Working group that aim to broaden CSS layout capabilities and reduce or eliminate the need for client-side JavaScript. These proposals employ well-defined strategies each with their own set of specific properties. If adopted, these proposals will increase substantially the size and complexity of CSS implementations as well as CSS syntax.

We propose a more general-purpose CSS layout solution that brings scripting unobtrusively into CSS. This solution enables a wide number of layout strategies to be defined in terms suitable to each. This general-purpose solution avoids the complexities that a multitude of independent solutions saddles on CSS implementers and developers.

CSS Scripting Layout Properties   top
A Scripting layout is encapsulated in a CSS layout-policy @-rule. A layout-policy @-rule defines a name that is referenced in layout-policy properties within rules. The body of a layout-policy @-rule is composed of properties with String values that are JavaScript expressions.
@layout-policy name
{
	initial-script:”arbitrary JavaScript”
	container-script:”arbitrary JavaScript”
	container-width:”…”
	container-height:”…”
	rectangle-attributes:”JavaScript Associative Array”
	left:”arbitrary JavaScript”
	horizontal-center:”…”
	right:”…”
	width:”…”
	top:”…”
	vertical-center:”…”
	bottom:”…”
	height:”…”
}

initial-script is arbitrary JavaScript that is executed to define values, functions, or any other JavaScript object that may then be referenced in the expressions of other constraint properties. It is executed only once per layout request.

container-script is arbitrary JavaScript that is executed to define values, functions, or any other JavaScript object that may then be referenced in the expressions of other constraint properties. It may be executed multiple times per layout request depending on the number of cycles required to resolve the constraints.

container-width and container-height properties are JavaScript expressions that must compute to a JavaScript Number, the value of which determines the width or height of the container. These properties may also be ordinary length or percentage values.

rectangle-attributes defines a JavaScript associative array. This associative array defines a set of name-value pairs whereby the name defines a new arbitrary attribute applicable to each child element of the container. The attribute value is a JavaScript expression.

The other constraint properties are JavaScript expressions and apply to each of the child elements of a container. These properties must compute to a JavaScript Number, the value of which determines the corresponding aspect of the child element. These properties may also be ordinary length or percentage values.

Constraint and rectangle attribute JavaScript expressions are evaluated lazily, at most once per distinct reference per layout resolution execution cycle. Each subsequent reference uses the result of the first evaluation. A reference is distinct on each child element on which the expression applies.

layout-policy @-rules are referenced by name in CSS rules.

A layout-policy property is set in a rule that is applied to a container html element in which case the layout policy constraints are applied to the container and its immediate child elements.

.container
{
	layout-policy:”policy1 policy2”
	initial-script:”arbitrary JavaScript”
	container-script:”arbitrary JavaScript”
	container-width:”…”
	container-height:”…”
}

layout-policy values may reference more than one policy. In this case subsequent policies override and augment values from preceding policies.

Other properties may be included in a rule to override or augment corresponding layout-policy @-rule values.

Child elements may override or augment the constraint values of a layout policy.

.child
{
	rectangle-attributes:”JavaScript Associative Array”
	left:”arbitrary JavaScript”
	…
}

A rectangle-attributes specification in a successive policy reference or on a rule overrides and augments the value in the initial policy. In other words, the rectangle-attributes value used in the computation is the amalgam of all the rectangle-attributes specified.

An overriding constraint with a value of none rescinds any prior constraint value rendering it unconstrained.

CSS Layout Objects and Interfaces   top
The expressions of the new CSS properties may reference new global objects defined in the CSS Layout JavaScript runtime environment.

A container object supports the CSSContainer interface that extends the Rectangle interface. A container object represents the container on which a layout policy is defined.

Rectangle
{
	readonly attribute double left;
	readonly attribute double right;
	readonly attribute double horizontal_center;
	readonly attribute double top;
	readonly attribute double bottom;
	readonly attribute double vertical_center;
	readonly attribute double width;
	readonly attribute double height;
	readonly attribute double preferred_width;
	readonly attribute double preferred_height;
	readonly attribute double current_width;
	readonly attribute double current_height;
	double em(in double x);
	double ex(in double x);
	double inch(in double x);
	double cm(in double x);
	double mm(in double x);
	double pc(in double x);
	double pt(in double x);
}

The preferred values refer to the sizes of a rectangle’s unconstrained values. The current values refer to the sizes of a rectangle prior to the application of any constraint.

CSSContainer : Rectangle
{
	readonly attribute CSSRectangleList children;
	readonly attribute long numChildren;
}

A CSSContainer maintains an ordered list of child elements. The individual child elements are represented in the global execution environment by objects that support the CSSRectangle interface that also extends the Rectangle interface. CSSRectangle objects support referencing rectangle-attributes properties by name. The object returned represents the computational result of the attribute value’s expression. CSSRectangle objects may be referenced by name from the CSSContainer returning either a CSSRectangleList or CSSRectangle. The CSSRectangle name value is the id of the HTML element that it represents.

CSSRectangle: Rectangle
{
	readonly attribute unsigned long position;
	readonly attribute String name;
	readonly attribute CSSRectangle predecessor;
	readonly attribute CSSRectangle successor;
}

CSSRectangle objects may be referenced abstractly in expressions through global objects rectangle, predecessor, and successor. rectangle represents the CSSRectangle object on which behalf a constraint or attribute expression is executing. predecessor, and successor represent the preceding and succeeding CSSRectangle objects of rectangle in the container’s ordered list either of which may be null. These values change throughout execution as expressions are evaluated.

A rectangles global object supports the CSSRectangleList interface. This object represents the ordered list of elements in a container. CSSRectangleList objects are immutable.

CSSRectangleList objects support indexing values to return corresponding CSSRectangle objects.

A sublist of a CSSRectangleList may be constructed from an existing CSSRectangleList by referencing it as a function with integer arguments:

CSSRectangleList(start, end, stride, count)

start and end indicate a range of index values. start may be greater than end indicating that the values are set in reverse order.

The lesser of start and end must be between zero and one less than the CSSRectangleList length.

The greater of start and end must be between one and the CSSRectangleList length.

stride indicates how many values to skip between successive values and count indicates how any values to include each stride. count must be less than or equal to stride.

Both stride and count default to one.

A new CSSRectangleList may also be constructed from an existing CSSRectangleList by referencing it as a function with an Array of integer values. The integer values represent the indices of values to include in the new CSSRectangleList.

Additionally, CSSRectangleList objects support referencing rectangle-attributes properties by name. A CSSRectangleListValue is returned to represent these values.

CSSRectangleList
{
 	readonly attribute unsigned long length;
	readonly attribute CSSRectangleListValue position;
	readonly attribute CSSRectangleListValue left;
	readonly attribute CSSRectangleListValue right;
	readonly attribute CSSRectangleListValue horizontal_center;
	readonly attribute CSSRectangleListValue top;
	readonly attribute CSSRectangleListValue bottom;
	readonly attribute CSSRectangleListValue vertical_center;
	readonly attribute CSSRectangleListValue width;
	readonly attribute CSSRectangleListValue height;
	readonly attribute CSSRectangleListValue preferred_width;
	readonly attribute CSSRectangleListValue preferred_height;
	readonly attribute CSSRectangleListValue current_width;
	readonly attribute CSSRectangleListValue current_height;
      	CSSRectangleListValue em(in double x);
      	CSSRectangleListValue ex(in double x);
      	CSSRectangleListValue inch(in double x);
      	CSSRectangleListValue cm(in double x);
      	CSSRectangleListValue mm(in double x);
      	CSSRectangleListValue pc(in double x);
      	CSSRectangleListValue pt(in double x);
	CSSRectangleListIterator iterator();
	CSSRectangleList remove(in int x);
	CSSRectangleList remove(in int x, int length);
	CSSRectangleList remove(in CSSRectangle x);
      	CSSRectangleList append(in CSSRectangle x);
      	CSSRectangleList append(in CSSRectangleList x);
	long indexOf(in CSSRectangle x);
	boolean contains(in CSSRectangle x);
}

A CSSRectangleListIterator provides a simple means to iterate through a CSSRectangleList.

CSSRectangleListIterator 
{
      readonly attribute unsigned long index;
      readonly attribute CSSRectangle next;
      readonly attribute boolean more;
}

A CSSRectangleListValue represents a set of values from a CSSRectangleList. CSSRectangleListValue objects support indexing values to return objects representing the corresponding values in the list.

CSSRectangleListValue : CSSRectangleListFilter
{
	readonly attribute double min;
	readonly attribute double max;
	readonly attribute double sum;
	readonly attribute double avg;
	readonly attribute double stddev;
	readonly attribute double variance;
	readonly attribute CSSRectangleList sort;
	readonly attribute CSSRectangleListFilter exclude;
	readonly attribute CSSRectangleListFilter truncate;
	readonly attribute CSSRectangleListFilter cumulate;
	readonly attribute CSSRectangleListValueRect rect;
}

A CSSRectangleListFilter represents a set of operations that may be executed on a CSSRectangleListValue. These operations return a CSSRectangleListFilterOp.

CSSRectangleListFilter
{
	CSSRectangleListOp eq;
	CSSRectangleListOp ne;
	CSSRectangleListOp le;
	CSSRectangleListOp lt;
	CSSRectangleListOp ge;
	CSSRectangleListOp gt;
}

A CSSRectangleListFilterOp represents a set of operations that may be executed on a CSSRectangleListFilter. These operations return a new CSSRectangleList.

CSSRectangleListFilterOp
{
	readonly attribute CSSRectangleList left;
	readonly attribute CSSRectangleList right;
	readonly attribute CSSRectangleList horizontal_center;
	readonly attribute CSSRectangleList top;
	readonly attribute CSSRectangleList bottom;
	readonly attribute CSSRectangleList vertical_center;
	readonly attribute CSSRectangleList width;
	readonly attribute CSSRectangleList height;
	readonly attribute CSSRectangleList preferred_width;
	readonly attribute CSSRectangleList preferred_height;
	readonly attribute CSSRectangleList current_width;
	readonly attribute CSSRectangleList current_height;
}

CSSRectangleListFilterOp objects may be referenced as a function with a single numeric argument.

Additionally, CSSRectangleListFilterOp objects support referencing rectangle-attributes properties by name. A CSSRectangleList is returned to represent the value of the operation.

A CSSRectangleListValueRect represents a set of operations that return a CSSRectangle object.

CSSRectangleListValueRect
{
	readonly attribute CSSRectangle min;
	readonly attribute CSSRectangle max;
}

The following examples illustrate valid usage:

 

Expression Return Value
container.em(1) The number of pixels in 1em of the container’s font
rectangles.width.max the maximum width of all the rectangles in the CSSRectangleList
rectangles.width.rect.max the CSSRectangle that has the maximum width of all the rectangles in the list
rectangles.width.sum the sum of the widths of the rectangles in the list
rectangles.width.gt(100) A new CSSRectangleList including only those CSSRectangle objects with a width greater than 100px
rectangles.preferred_width. gt.current_width A new CSSRectangleList including only those CSSRectangle objects with a preferred width greater than their current width.
rectangles.width.exclude. gt(100) A new CSSRectangleList excluding those CSSRectangle objects with a width greater than 100px
rectangles.width.truncate. gt(100) A new CSSRectangleList truncated at the position of the first CSSRectangle that has a width greater than 100px
rectangles.width.cumulate. gt(100) A new CSSRectangleList truncated at the position of the first CSSRectangle that has a width that when summed with all preceding CSSRectangle widths is greater than 100px
rectangles(0, rectangles.length, 2) A new CSSRectangleList composed of every other CSSRectangle in the list
rectangles(rectangles.length, 0) A new CSSRectangleList in reverse order

 

Resolving Constraints   top
The constraint resolver executes the initial-script JavaScript to initialize the execution environment. The initial-script values referenced in the container’s layout-policy references are executed in the order presented followed by the initial-script value of the container itself.

After initialization the constraints for all the contained elements are resolved deterministically according to how dependencies among the constraints are expressed in the constraint values.

For instance, the top side of an element may be affixed to the bottom side of its predecessor according to the following constraint:

top:”predecessor.bottom”

In this case, the execution of the top constraint is interrupted in order to determine the bottom constraint of the predecessor. The predecessor may or may not have an explicit bottom constraint. If the constraint exists, it is evaluated, the result returned, and the top constraint execution is resumed. If the bottom constraint does not exist then its value is determined via other related constraints in the vertical dimension, e.g. a top and height constraint. Once all constraints are satisfied a layout computation is complete.

The constraint resolver strategy involves the repeated computation of container size and child rectangle configurations within the container. The child rectangle geometries are held constant at their current values during the computation of the container size. Conversely, the container size is held constant during the computation of the child rectangle configurations.

A global Boolean value, sizing, is defined in the runtime environment to distinguish between the computation of the container size and the child rectangle configurations.

The constraint resolver uses a set of heuristics to determine when to terminate. The primary heuristic is to stop when the last container size computation is a repeat of some prior computation, but only when all child rectangles’ sizes are at least as large as their preferred sizes, i.e. their content does not overextend their bounds. However, this second heuristic is relaxed in the case where all rectangle preferred sizes are a repeat of some prior computation. In this case, it is probably impossible to configure the child rectangles without some overextension.

In under-constrained or abstractly constrained cases multiple solutions may be indicated by a particular layout specification and set of content. In this case, the solution with the least area container in which all child rectangles fit their bounds is chosen. In cases where child rectangles must overextend then the configuration with the largest area container prevails.

This constraint resolution strategy enables layout solutions for more abstractly constrained specifications heretofore unrealizable in CSS while retaining the ability to resolve more typically constrained layout specifications quickly and efficiently.

A detailed discussion of size negotiation among elements is beyond the scope of this paper, but the subject is worthy of thorough examination. Geometry management as prescribed by the X Toolkit Intrinsics XtQueryGeometry1 is a good reference for this subject.

In a conventional layout specification, constraints are explicit and convergence to a solution occurs in one or two iterations. In these instances layouts are resolved quickly consuming little CPU time.

More interestingly, specifications with more abstract constraints may be realized. These make use of feedback from suboptimal early generation solutions to improved succeeding generation solutions converging to a final solution in the manner of a genetic algorithm. Example specifications follow that illustrate layout policies that include these features. Moreover, these examples will show how layouts can adapt to changes in screen real estate from window resize events.

CSS Scripting Layout – Security issues   top
The global object for the CSS Layout JavaScript runtime environment is an ordinary Object. Not using the browser window as the global object reduces or eliminates the possibility of any serious cross-site scripting (XSS) attack. As such, the CSS Layout JavaScript runtime environment does not include any of the HTML DOM objects or any client-side JavaScript Browser objects, including:
  • Window
  • Navigator
  • Screen
  • History
  • Location
  • Document

Likewise, the Asynchronous JavaScript and XML (AJAX) XMLHttpRequest object is unavailable in this runtime environment.

CSS Scripting Layout - Sample Implementation   top
To validate the CSS Scripting Layout specification a sample implementation was coded as an extension to Google Chrome. A 12.7MB zipped windows XP compatible executable of this implementation is located at the eFORCE site here. In this implementation scripting layout is limited to the elements of container elements that are positioned absolutely.
Comments on Layout in the Current CSS Standard

Dissatisfaction with CSS layout capability has been expressed by many in the Web Development community10,11,12,13,14,15,16,17,18,19,20 including members of the W3C CSS WG.21,22,23 The CSS Scripting Layout Model described here resolves many, if not most, of these legitimate concerns.

CSS, apparently, was conceptualized to enable a newspaper-like layout in a Web page.24,25 Whatever the case, in regard to layout, it should not be considered controversial to state that CSS was influenced primarily by the demands of print media and little on User Interface demands. This is understandable since, at the time, the WWW was dominated by static print media. However, rendering Web content now involves much more than mere typography. The Web has evolved into a GUI rich environment in which JavaScript Libraries like YUI26, Dojo Toolkit27, Ext JS28 , and others29 that enable layout features not easily achievable or impossible to achieve in CSS.

Interestingly, thirty-two leaders in the fields of web design and development interviewed for a Teach the Web monograph ranked layout third in importance among 62 skills that students should know by the time they graduate.30 This is further testimony to the inadequate state of CSS regarding layout and a need for tools and, moreover, new standards that address its shortcomings.

There are several layout related proposals31,32,33,34,35 in various states of development before the CSS Working Group and others36 that are not. These proposals appear to address various shortcomings, but do so at the cost of greatly increasing complexity with the introduction of a multitude of new properties that are largely mutually exclusive. The layout specification described here could mitigate the need for some of these proposals.

Conclusion

Layout is inherently complex. Layout designs must adapt to any imaginable change in screen size, configuration, or composition in real-time. The possibilities are limitless. It is an impossible task for any single high-level specification, or even a small set of specifications, to cope with every conceivable circumstance.

The W3C's Web Content Accessibility Guidelines' checkpoint 3.3, a priority-2 checkpoint, states "use style sheets to control layout and presentation."37 With this directive in mind it is incumbent on the W3C to provide lower-level tools to enable the broadest set of layout strategies and handle unforeseeable eventualities. As a practical matter, the most suitable tools for this purpose must incorporate aspects of actual programming languages. We believe that the combination of a scripting language and the Object Interfaces presented here meets this challenge most effectively in conformance with W3C's design principles.38

1 X Toolkit Intrinsics - Chapter 6 - Geometry Management
http://lesstif.sourceforge.net/doc/super-ux/g1ae03e/part1/contents.html

10We need something better for layout.
http://ajaxian.com/archives/css-for-layout-another-rant

11Wanted: Layout System
http://meyerweb.com/eric/thoughts/2009/02/17/wanted-layout-system/

12Here are a short list of the some disadvantages of using pure CSS on web layouts and designs.
http://www.articlesbase.com/web-design-articles/advantages-and-disadvantages-of-using-css-833019.html

13There are lots of things which we’d like to put in CSS but don’t because CSS just can’t do many of the things we should expect of it. Real-world CSS is likely to get longer, not shorter, as CSS evolves toward… all manner of complex layouts for which we currently turn to table elements and layout systems...
http://alex.dojotoolkit.org/2008/08/css-variables-are-the-future/

14There’s also no indication that the [W3C CSS Working Group] has taken stabs exposing the expressive power that Microsoft exposed with CSS Expressions.
http://alex.dojotoolkit.org/2007/12/the-w3c-cannot-save-us/

15Epicycles: are complex css layouts the new nested tables?
http://www.brucelawson.co.uk/2006/are-complex-css-layouts-the-new-nested-tables/

16If CSS layout code were as easy to write as HTML tables, making the leap would be a no-brainer; …the tools that CSS provides are not suited to the layout tasks we want to accomplish.
http://carsonified.com/blog/design/tables-the-next-evolution-in-css-layout/

17Real world layout is still dependent on source order. Some effects (equal height columns) are still hard to do... CSS and web standards keep popping up where they're least expected.
http://www.paulhammond.org/2006/06/atmedia/ericmeyer

18… layouts still requires trickery and some magic even after all this time.
http://www.nczonline.net/blog/2007/10/08/css-sucks/

19The fundamental problems with CSS3
http://mattwilcox.net/archive/entry/id/1031/

20Why CSS needs to borrow from programming languages
http://mattwilcox.net/archive/entry/id/991/

21Layout Is Expensive
http://fantasai.inkedblade.net/weblog/2009/layout-is-expensive/

22Web layout standards so far have taken a lot from the history of formatting printed documents and very little from the history of designing user interfaces. We need more of a balance...
http://dbaron.org/log/2007-09#e20070920a

23WaSP Community CSS3 Feedback 2008 - Layout
http://fantasai.inkedblade.net/style/discuss/wasp-feedback-2008#layout

24Chapter 20 of Cascading Style Sheets, designing for the Web
http://www.w3.org/Style/LieBos2e/history/

25Cascading HTML style sheets -- a proposal
http://www.w3.org/People/howcome/p/cascade.html

26An open-source JavaScript library for building richly interactive web applications
http://en.wikipedia.org/wiki/Yahoo!_UI_Library

27dojox.layout Experimental and Extended Layout Widgets
http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/layout/README

28A cross-browser JavaScript library for building rich internet applications
http://www.extjs.com/

2910 Promising CSS Framework That Worth A Look
http://www.webdesignbooth.com/10-promising-css-framework-that-worth-a-look/

30Perspectives on web education: What to teach the next generation of web professionals.
http://teachtheweb.com/monograph.php

31Template Layout Module
http://www.w3.org/TR/css3-layout/

32Multi-column Layout Module
http://www.w3.org/TR/css3-multicol/

33Table Model
http://www.w3.org/TR/CSS2/tables.html#table-display

34Flexible Box Layout Model
http://www.w3.org/TR/css3-flexbox/

35Grid Positioning Module Level 3
http://www.w3.org/TR/css3-grid/

36Matrix Layout
http://snook.ca/technical/matrix-layouts/

37Checkpoint 3.3
http://www.w3.org/TR/WCAG10-TECHS/#tech-style-sheets

38What is a good standard?
http://www.w3.org/People/Bos/DesignGuide/introduction

 
 
Example 1 – Introductory Concepts   back
The HTML in Example 1 produces the screen shot in Figure 1.

The rendering of this example demonstrates many of the features of CSS Script Layout.

Example 1 – Nested Containers

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>Nested Containers</title>

<style type="text/css">

@layout-policy pack_column {
    initial-script: "\
        var margin=container.em(0.5);\
    ";
    rectangle-attributes: "{\
        'topOffset':0\
    }";
    horizontal-center:"container.width/2";
    top: "rectangle.topOffset+margin\
        +(predecessor ? predecessor.bottom : 0)";
    container-height: "margin*(rectangles.length+1)\
        +rectangles.height.sum+rectangles.topOffset.sum";
    container-width: "2*margin+rectangles.width.max";
}
@layout-policy override {
    initial-script: "\
        var margin=container.em(0.25)\
    ";
    horizontal-center:none;
    left:"margin";
}
@layout-policy pack_row {
    initial-script: "\
        var margin=0;\
    ";
    vertical-center:"container.height/2";
    left:"margin+(predecessor ? predecessor.right : 0)";
    container-width:"margin*(rectangles.length+1)\
        +rectangles.width.sum";
    container-height:"2*margin+rectangles.height.max;";
}
.body {
    layout-policy: 'pack_column';
    position:relative;
    border:1px black dashed;
    padding:0px;
}
.container {
    layout-policy: 'pack_row';
    initial-script: "margin=container.ex(2);";
    position:absolute;
    border:1px black solid;
    padding:0px;
 }
.container1 {
    layout-policy: 'pack_column override';
    width:130px;
    position:absolute;
    border:1px black dotted;
    margin:0px;
    padding:0px;
 }
.text {
    position:absolute;
    border:1px black dashed;
    padding:0px;
 }
.extension {
    rectangle-attributes: "{\
        'topOffset':'container.em(1)+margin'\
    }";
    width:200px;
    padding:10px;
 }
</style>

</head>

<body class='body'>
<span class='text'>test nesting containers</span>

<span class='container'>
a nested container that overrides the default margin.<br>
this text is in a relative span and<br>is not constrained by the container.
<span class='text'>
this&nbsp;span&nbsp;of&nbsp;text&nbsp;is&nbsp;centered&nbsp;vertically
</span>
<button style='position:absolute;'>button</button>

<span class='container1'>
relative text
<span class='text extension'>
this span has an explicit padding and width specification and a topOffset rectangle attribute.
</span>
<span class='text' style='width:150px'>
notice also the override policy specification overrides the margin and alignment...
</span>
<span class='text'>hence the spans are now left aligned and the margin is smaller.
</span>

</span>

</span>
</body>
</html>

Figure 1 - Nested Containers

This layout renders in less than 32 milliseconds on a Dell LATITUDE D630 Laptop (Intel Core 2 Duo T7500 2.20GHz, 2.49 GB RAM) running MS Windows XP V2002 Service Pack 3.

 
 
Example 2 – Three-Column Presentation   back
The Common Three-Column Presentation 2,3,4 HTML in Example 2 produces the screen shot in Figure 2.

The rendering of this example demonstrates how elements may be referenced by their HTML id in the script. Additionally, in this example there is no dependency on the order of the elements in the HTML as to where they are rendered. This is an important point for those concerned with Search Engine Optimization (SEO).

The totality of the layout here is distributed among the rules of each element in the window. Notable here is that the desired result is clearly evident from the constraint specifications within each rule and presented rationally without resorting to hacks or tricks and without any compromises. All elements are free to resize as required by their content.

Example 2 – Common Three-Column Presentation

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>Three Column Layout</title>
<style type="text/css">

@layout-policy entire_window {
initial-script: "\
var margin=4;\
var content_area=container.content_area;\
var header=container.header;\
var header_content=container.header_content;\
var footer=container.footer;\
var footer_content=container.footer_content;\
var primary_navigation=container.primary_navigation;\
var secondary_navigation=container.secondary_navigation;\
var min_content_width = 200;\
var max_content_width = 600;\
";
container-script: "\
var content_width = container.width-2*margin-\
	primary_navigation.width-secondary_navigation.width;\
";
container-height:100%;
container-width:100%;
}

#body {
    position:relative;
    layout-policy: 'entire_window';
    border:0px black solid;
    margin:0px;
    padding:0px;
}

#content_area {
    top:"header.bottom";
    bottom:"footer.top";
    left:"primary_navigation.right";
    width:"content_width<min_content_width?min_content_width:\
	content_width>max_content_width?max_content_width:content_width";
    position:absolute;
    border:1px black solid;
}

#primary_navigation {
    left:"margin";
    width:"rectangle.ex(10)+8+container.width*0.1;";
    top:"header.bottom";
    bottom:"footer.bottom";
    position:absolute;
    border:1px black solid;
}

#secondary_navigation {
    top:"header.bottom";
    bottom:"footer.bottom";
    left:"content_area.right";
    width:"rectangle.ex(8)+8+container.width*0.1;";
    position:absolute;
    border:1px black solid;
}

#header {
    top:"margin";
    height:"header_content.height+2*margin";
    left:"margin";
    right:"secondary_navigation.right";
    position:absolute;
    border:1px black solid;
}

#header_content {
    width:"header.width-2*margin";
    vertical-center:"header.vertical_center";
    horizontal-center:"header.horizontal_center";
    position:absolute;
    border:1px black solid;
}

#footer {
    height:"footer_content.height+2*margin";
    top:"header.bottom+Math.max(content_area.preferred_height,\
primary_navigation.preferred_height-footer.height,\
secondary_navigation.preferred_height-footer.height)";
    left:"primary_navigation.right";
    right:"secondary_navigation.left";
    position:absolute;
    border:1px black solid;
}

#footer_content {
    width:"footer.width-2*margin";
    horizontal-center:"footer.horizontal_center";
    vertical-center:"footer.vertical_center";
    position:absolute;
    border:1px black solid;
}

  </style>
</head>


<body id='body' class='body'>


<span id='content_area'>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem 
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae 
ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt 
explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut 
odit aut fugit, sed quia consequuntur magni dolores eos qui ratione 
voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum 
quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam 
eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat 
voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam 
corporis suscipit laboriosam, nisi ut aliquid ex ea commodi 
consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate 
velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum 
fugiat quo voluptas nulla pariatur?
</span>

<span id='primary_navigation'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse 
massa lacus, consectetur vitae commodo sed, aliquet eget sapien. 
Quisque erat odio, convallis non aliquam vitae, pulvinar a diam. 
In hac habitasse platea dictumst. Aenean non tempor ipsum. Sed scelerisque 
fringilla ligula at laoreet. Cras posuere metus at ligula posuere in 
consequat lorem malesuada. Sed id lobortis nulla.
</span>

<span id='secondary_navigation'>
Fusce enim sem, ornare in ornare nec, ornare sed neque. Ut sed felis 
orci, in pretium lectus. Cras nec felis sed nibh venenatis dignissim in 
sit amet massa. Cras sodales mollis arcu, quis sagittis tellus euismod 
eu. Nulla facilisi. Aliquam ultrices consequat rutrum. Quisque pharetra 
adipiscing porta. Nullam sem urna, fringilla tempus aliquet a, ornare 
non risus.
</span>

<span id='header_content'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum 
vestibulum fringilla interdum. Fusce suscipit vehicula nunc, nec 
sagittis risus mollis non. Cras non rhoncus magna. Vestibulum ante 
ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; 
Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis 
dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel 
eros iaculis ac rhoncus nibh tincidunt.
</span>

<span id='footer_content'>
Fusce quis lacus ligula, a dictum metus. Aenean risus odio, sagittis ac 
posuere vel, viverra et erat. Aenean eros lorem, fringilla ut aliquam 
id, pulvinar et nulla. Pellentesque imperdiet eros non odio faucibus 
fringilla. Nam ut nulla at tellus vestibulum mattis.</span>
<span id='header'</span>
<span id='footer'></span>

</body>

</html>

Figure 2 - Common Three Column Presentation

The Three-Column layout renders in 16 milliseconds on a Dell LATITUDE D630 Laptop (Intel Core 2 Duo T7500 2.20GHz, 2.49 GB RAM) running MS Windows XP V2002 Service Pack 3.

2 In Search of the Holy Grail
http://www.alistapart.com/articles/holygrail/
3 CSS Three Column Liquid Layout
http://www.manisheriar.com/holygrail/index.htm
4 Why CSS should not be used for layout
http://www.flownet.com/ron/css-rant.html
 
 
Example 3 – HTML Table comparison   back
The HTML in Example 3 produces the screen shot in Figure 3. In the first row the layout policy accounts for and minimizes a cell’s total area rather than relying on a cell’s width as in the HTML table below it. Deficiencies with table layout are described in Poorly Laid-out Tables.5

Example 3 – Script vs. HTML Table

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>Script vs. HTML Table</title>
<style type="text/css">

@layout-policy pack_column {
initial-script: "\
var margin=1;\
var space=(rectangles.length+1)*margin;\
";
width:"container.width";
height:"rectangle.preferred_height";
top:"margin+(predecessor ? predecessor.bottom : 0)";
container-height:"space+rectangles.preferred_height.sum";
container-width:"rectangles.preferred_width.max";
}

@layout-policy least_area_horizontal {
initial-script: "\
var margin=2;\
var space=(rectangles.length-1)*margin;\
var governor=-0.24;\
var accelerator=2;\
";
container-script: "\
var reserved=rectangles.pliant.eq(false);\
var pliant=rectangles.pliant.ne(false);\
var usable_width=container.width-space-reserved.preferred_width.sum;\
var area_ratio=usable_width/pliant.area.sum;\
";
rectangle-attributes: "{\
'current_area':'rectangle.current_width*rectangle.current_height',\
'preferred_area':'rectangle.preferred_width*rectangle.preferred_height',\
'area':'rectangle.preferred_area*accelerator+rectangle.current_area*governor',\
'max_width':'rectangle.preferred_width>=rectangle.width?rectangle.preferred_width:rectangle.width',\
'pliant':'rectangle.pliant!==false&&rectangle.preferred_width<=rectangle.current_width'\
}";
top:0;
height:"container.height";
width:"rectangle.pliant?rectangle.area*area_ratio:rectangle.preferred_width";
left:"predecessor ? predecessor.right+margin : 0";
container-width:"rectangles.max_width.sum+space";
container-height:"rectangles.preferred_height.max";
}
.body {
    padding:0px;
    margin:0px;
    layout-policy: 'pack_column';
    border:1px black solid;
    position:relative;
    container-width:100%;
}
/* script layout rules */
.text {
    margin:0px;
    position:absolute;
    border:1px black solid;
    padding:0px;
}
.row {
    layout-policy: 'least_area_horizontal';
    position:absolute;
    border:2px black dotted;
    margin:0px;
    padding:0px;
}
/* html table rules */
.table {
    position:absolute;
    border:2px black dotted;
    margin:0px;
    padding:0px;
}
.ttext {
    vertical-align:top;
    margin:0px;
    border:1px black solid;
    padding:0px;
}

  </style>
</head>

<body id='body' class='body'>

<div id='top' class='row'>

<span id='text2' class='text'>
<img src="small.gif"><img src="small.gif"><img src="big.gif"><img src="big.gif">
</span>

<span id='text1inner' class='text'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum 
vestibulum fringilla interdum. Fusce suscipit vehicula nunc, nec 
sagittis risus mollis non. Cras non rhoncus magna. Vestibulum ante 
ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; 
Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis 
dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel 
eros iaculis ac rhoncus nibh tincidunt.
</span>

<span id='text1inner' class='text'>
Fusce quis lacus ligula, a dictum metus. Aenean risus odio, sagittis ac 
posuere vel, viverra et erat. Aenean eros lorem, fringilla ut aliquam 
id, pulvinar et nulla. Pellentesque imperdiet eros non odio faucibus 
fringilla. Nam ut nulla at tellus vestibulum mattis. Fusce at tincidunt 
nunc. Aliquam pharetra faucibus nisl, auctor dignissim tortor vehicula 
rutrum. Pellentesque tincidunt mi ut elit congue sit amet eleifend dui 
euismod. Donec luctus, lorem et placerat pulvinar, justo nunc dapibus 
lorem, id porta velit diam sed diam. Nulla et erat libero. Donec auctor 
sapien in dolor pretium ornare.
</span>
</div>

<table id='table' class='table'>
<tr class='ttext'>

<td id='text2' class='ttext'>
<img src="small.gif"><img src="small.gif"><img src="big.gif"><img src="big.gif">
</td>

<td id='text1inner' class='ttext'>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum 
vestibulum fringilla interdum. Fusce suscipit vehicula nunc, nec 
sagittis risus mollis non. Cras non rhoncus magna. Vestibulum ante 
ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; 
Nullam eleifend sapien velit. Cum sociis natoque penatibus et magnis 
dis parturient montes, nascetur ridiculus mus. Quisque gravida erat vel 
eros iaculis ac rhoncus nibh tincidunt.
</td>
<td id='text1inner' class='ttext'>
Fusce quis lacus ligula, a dictum metus. Aenean risus odio, sagittis ac 
posuere vel, viverra et erat. Aenean eros lorem, fringilla ut aliquam 
id, pulvinar et nulla. Pellentesque imperdiet eros non odio faucibus 
fringilla. Nam ut nulla at tellus vestibulum mattis. Fusce at tincidunt 
nunc. Aliquam pharetra faucibus nisl, auctor dignissim tortor vehicula 
rutrum. Pellentesque tincidunt mi ut elit congue sit amet eleifend dui 
euismod. Donec luctus, lorem et placerat pulvinar, justo nunc dapibus 
lorem, id porta velit diam sed diam. Nulla et erat libero. Donec auctor 
sapien in dolor pretium ornare.
</td>
</tr>
</table>

</body>
</html>

Figure 3 - Script vs. HTML Table

The layout in Figure 3 renders in less than 32 milliseconds on a Dell LATITUDE D630 Laptop (Intel Core 2 Duo T7500 2.20GHz, 2.49 GB RAM) running MS Windows XP V2002 Service Pack 3.

5Poorly Laid-out Tables
http://nothings.org/computer/badtable/
 
 
 
Example 4 – Advanced Concepts – Near Optimal Least Area Layout   back
The HTML in Example 4 produces the screen shots in Figures 4 and 5. The Near Optimal Least Area layout nests containers to a depth of four with varying layout policies for each. Notable here is that in the execution of the layout policies the constraint resolver searches for and converges on solutions that minimize the area taken by the rectangles for a given width of the window. There is no guarantee that the most optimal layout is found, but only one that approaches it which is likely acceptable if not imperceptible from the optimum to the average viewer.

A description of the actual layout policies and how they function is beyond the scope of this paper. More to the point is that layouts may be developed and shared among developers without the need for end users to understand the execution details. De facto or even de jure standards could emerge from this process.

Example 4 – Near Optimal Least Area

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>Near Optimal Least Area</title>
<style type="text/css">

@layout-policy pack_column {
initial-script: "\
var margin=1;\
var space=(rectangles.length+1)*margin;\
";
width:"container.width";
height:"rectangle.preferred_height";
top:"margin+(predecessor ? predecessor.bottom : 0)";
container-height:"space+rectangles.preferred_height.sum";
container-width:"rectangles.preferred_width.max";
}

@layout-policy proportional_width {
initial-script: "\
var margin=2;\
var governor=-0.25;\
var accelerator=2;\
var space=(rectangles.length-1)*margin;\
";
container-script: "\
var reserved=rectangles.pliant.eq(false);\
var pliant=rectangles.pliant.ne(false);\
var usable_width=container.width-space-reserved.preferred_width.sum;\
var area_ratio=usable_width/pliant.area.sum;\
";
rectangle-attributes: "{\
'area':'rectangle.preferred_width*rectangle.preferred_height*accelerator+\
rectangle.current_width*rectangle.current_height*governor',\
'max_width':'rectangle.preferred_width>=rectangle.width?rectangle.preferred_width:rectangle.width',\
'pliant':'rectangle.pliant!==false&&rectangle.preferred_width<=rectangle.current_width'\
}";
top:0;
height:"container.height";
width:"rectangle.pliant?rectangle.area*area_ratio:rectangle.preferred_width";
left:"predecessor ? predecessor.right+margin : 0";
container-width:"rectangles.max_width.sum+space";
container-height:"rectangles.preferred_height.max";
}

@layout-policy proportional_height {
initial-script: "\
var margin=2;\
var governor=-0.25;\
var accelerator=2;\
var space=(rectangles.length-1)*margin;\
";
container-script: "\
var reserved=rectangles.pliant.eq(false);\
var pliant=rectangles.pliant.ne(false);\
var usable_height=container.height-space-reserved.preferred_height.sum;\
var area_ratio=usable_height/pliant.area.sum;\
";
rectangle-attributes: "{\
'area':'rectangle.preferred_width*rectangle.preferred_height*accelerator+\
rectangle.current_width*rectangle.current_height*governor',\
'pliant':'rectangle.pliant!==false&&rectangle.preferred_height<=rectangle.current_height'\
}";
top:0;
width:"container.width";
height:"rectangle.pliant?rectangle.area*area_ratio:rectangle.preferred_height";
top:"predecessor ? predecessor.bottom+margin : 0";
container-height:"rectangles.preferred_height.sum+space";
container-width:"rectangles.preferred_width.max";
}

.body {
    padding:0px;
    margin:0px;
    layout-policy: 'pack_column';
    border:1px black solid;
    position:relative;
    container-width:100%;
}
.column {
    position:absolute;
    padding:0px;
    margin:0px;
    layout-policy: 'proportional_height';
    border:2px black solid;
}
.text {
    margin:0px;
    position:absolute;
    border:1px black solid;
    padding:0px;
 }

.row {
    layout-policy: 'proportional_width';
    position:absolute;
    border:2px black dotted;
    margin:0px;
    padding:0px;
}

  </style>
</head>

<body id='body' class='body'>

<div id='top' class='row'>

<span id='textimagemixlong' class='text'>
<img src="small.gif" border="0"> <img src="small.gif" border="0"> 
<img src="small.gif" border="0"> <img src="small.gif" border="0">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse 
massa lacus, consectetur vitae commodo sed, aliquet eget sapien. 
Quisque erat odio, convallis non aliquam vitae, pulvinar a diam.
<img src="small.gif" border="0"> <img src="small.gif" border="0"> 
<img src="small.gif" border="0"> <img src="small.gif" border="0">
In hac habitasse platea dictumst. Aenean non tempor ipsum. Sed 
scelerisque fringilla ligula at laoreet.
</span>

<span id='text2' class='text'> 
<img src="small.gif"> <img src="small.gif"> 
<img src="small.gif"> <img src="small.gif"> 
<img src="big.gif"> <img src="big.gif"> 
<img src="big.gif"> <img src="big.gif"> 
</span> 

<span id='text1inner' class='text'>
Cras posuere metus at ligula posuere
<img src="small.gif" border="0">
in consequat
<img src="small.gif" border="0">
lorem malesuada.
<img src="small.gif" border="0">
Sed id lobortis nulla.
<img src="small.gif" border="0">
Fusce enim sem, ornare in ornare nec, ornare sed neque. Ut sed felis 
orci, in pretium lectus. Cras nec felis sed nibh venenatis dignissim in 
sit amet massa. Cras sodales mollis arcu, quis sagittis tellus euismod eu.
</span>

<div id='inner' class='column'>

<span id='text1inner' class='text'>
Nulla facilisi. Aliquam ultrices
<img src="small.gif" border="0">
consequat
<img src="small.gif" border="0">
rutrum.
<img src="small.gif" border="0">
Quisque pharetra
<img src="small.gif" border="0">
adipiscing porta. Nullam sem urna, fringilla tempus aliquet a, ornare non risus.
</span>

<span id='text2inner' class='text'>
<img src="small.gif" border="0"> This is a nice simple paragraph of text,
<img src="small.gif" border="0"> 
which has been chosen to  height as the other cell, since they are about equally long.
</span>

</div>

</div>

<div id='bottom' class='row'>

<span id='textbr' class='text'>
This paragraph has encoded *<br>
line-breaks after each asterisk *<br>
to confound the layout.  Content *<br>
management systems may include *<br>
content with embedded html or *<br>
images that confound sensitive *<br>
css specifications. Content *<br>
authors often are unaware of where*<br>
their content is consumed.*<br>
</span>

<span id='textimagemixlong' class='text'>
<img src="small.gif" border="0"> <img src="small.gif" border="0"> 
<img src="small.gif" border="0"> <img src="small.gif" border="0">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem 
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae 
ab illo inventore veritatis et quasi architecto beatae vitae dicta
<img src="small.gif" border="0"> <img src="small.gif" border="0"> 
<img src="small.gif" border="0"> <img src="small.gif" border="0">
sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur 
aut odit aut fugit,
</span>

<div id='innerbottom' class='column'>

<div id='innerbottomrow' class='row'>

<span id='smallinner' class='text'>
<img src="small.gif" border="0"> <img src="small.gif" border="0"> 
<img src="small.gif" border="0"> <img src="small.gif" border="0">
</span>

<span id='text1inner' class='text'>
sed quia consequuntur magni
<img src="small.gif" border="0">
dolores eos
<img src="small.gif" border="0">
qui ratione
<img src="small.gif" border="0">
voluptatem sequi
<img src="small.gif" border="0">
nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit 
amet, consectetur, adipisci velit, sed quia non numquam eius modi 
tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. 
Ut enim ad minima
</span>

<span id='text2inner' class='text'>
<img src="small.gif" border="0">
veniam, quis
<img src="small.gif" border="0">
nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut 
aliquid ex ea commodi consequatur? Quis autem
</span>

</div>

<span id='text2inner' class='text'>
<img src="small.gif" border="0">
vel eum iure reprehenderit qui in ea
<img src="small.gif" border="0"> 
voluptate velit esse quam nihil molestiae consequatur, vel illum qui 
dolorem eum fugiat quo voluptas nulla pariatur?
</span>

</div>

</div>

</body>
</html>

Figure 4 - Near Optimal Least Area Layout

Example 4 is an extreme case demonstrating the ability of the containers to cooperate in the layout resolution. Note that no explicit heights or widths are specified. In this instance the layout adjusts to the content and vice versa in a virtuous cycle.

In situations where content is generated by a CMS team that is separate from the Web design team6 or where content may be reused in many applications not known in advance7,8 it may be necessary to leave element sizes unspecified and accommodate their natural sizes in a self-organizing layout. Otherwise poor renderings may result as demonstrated in the HTML table in Example 3.

In Figure 5 a resize widening the window results in the layout adjusting accordingly.

Figure 5 - Near Optimal Least Area Layout. Layout adjusts to increased window width.

The layout in Examples 4 and 5 renders in somewhere between 0.2 and 2.0 seconds, usually toward the lower end, depending on the window size as it unpredictably effects the rate of convergence. This may be acceptable performance for some applications.9

6 laying out images consistently within a design is difficult; especially when you hand the keys over to someone else to fill in the content.
http://www.alistapart.com/articles/figurehandler/
7 we must build pages that adapt to unpredictable content and unpredictable users.
http://blog.rebeccamurphey.com/2009/02/13/css-vs-tables-maybe-the-design-is-to-blame/
8 The challenge is writing CSS that looks good if you don't know ahead of time what your content is going to be.
http://rondam.blogspot.com/2009/02/css-and-meaning-of-life.html
9 Fast is better than slow. Slow is better than closed.
http://alex.dojotoolkit.org/2009/08/some-orthodox-heresies/

 

Print | posted on Thursday, July 16, 2009 10:56 AM

Feedback

Gravatar

 re: CSS Scripting Layout Specification

As I said on Ajaxian:

Great!! I’ve been touting about this type of approach to CSS before (just on an idea level), and even thought of coining it JSS (JavaScript Style Sheet). I think you have managed to make this approach (combining JS and CSS) work very well though. Combining the power of CSS and extending it with

JavaScript is IMO the best way to begin to extend CSS, since the standardisation and adoption of new properties takes so long. Besides, the JavaScript capabilities in modern browsers has made this approach much more viable.

I’m up for it!! Great work :)
7/17/2009 2:14 AM | Glen Somerville
Gravatar

# re: CSS Scripting Layout Specification

I've included the html of the examples included in this blog entry in the downloadable zip file. it also contains three other html files with policies demonstrating other features. I'll expound on these layouts in a future blog entry.
2/23/2010 9:21 AM | Darrel Karisch
Gravatar

 re: CSS Scripting Layout Specification

see blog entry http://blogs.eforceglobal.com/dkarisch/archive/2010/03/15/544.aspx for a HTML table emulation and an improved table layout implementation.
3/15/2010 11:42 AM | Darrel Karisch
Gravatar

 re: CSS Scripting Layout Specification

In consideration of the technical comprehension level of the general readership many details of the constraint resolution strategy are omitted from this blog entry.
The intention of this post is to foster discussion and promote a more open system for layout in CSS.

5/6/2010 10:50 AM | Darrel Karisch

 re: CSS Scripting Layout Specification

See How CSS Scripting Layout Can Help the Web Development Community at http://blogs.eforceglobal.com/dkarisch/posts/546.aspx
10/14/2010 8:42 AM | Darrel Karisch
Gravatar

# re: CSS Scripting Layout Specification

Pour mener à bien cette mission ultrasecrète, les cinq hommes devront vivre en permanence dans l'ombre...
12/17/2011 2:41 AM | watches
Gravatar

 re: CSS Scripting Layout Specification

since the standardisation and adoption of new properties takes so long. Besides, the Ios On Android Phone JavaScript capabilities in modern browsers has made this approach much more viable.
1/23/2012 1:06 AM | keeth
Gravatar

 re: CSS Scripting Layout Specification

After reading your article I was amazed. I know that you explain it very well. And I hope that other readers will also experience how I feel after reading your Andaman and Nicobar Islands Tourism article. I feel very grateful that I read this
5/30/2012 6:24 AM | poha
Gravatar

# re: CSS Scripting Layout Specification

I agree completely. These hardcore music posters are so much fun. And John is quite amusing too.
2/18/2013 2:46 AM | cialis pharmacie
Gravatar

# re: CSS Scripting Layout Specification

I've been browsing online more than 3 hours as of late, but I never found any fascinating article like yours. It is pretty value sufficient for me. In my view, if all webmasters and bloggers made just right content material as you probably did, the internet will likely be much more helpful than ever before.
3/2/2013 11:50 AM | Sofa Repair
Gravatar

# re: CSS Scripting Layout Specification

i like your blog thanks for sharing this blog i really like this keep it up Regards!!
3/12/2013 6:40 AM | ElevenBenefits
Gravatar

# re: CSS Scripting Layout Specification

i like this blog thanks for sharing this web site thanks keep it up!!!
3/17/2013 2:52 AM | Permanent Listing
Gravatar

# re: CSS Scripting Layout Specification

Each subsequent reference uses the result of the first evaluation. A reference is distinct on each child element on which the expression applies.
Gravatar

# re: CSS Scripting Layout Specification

Thanks browsing online more than 3 hours as of late, but I never found any fascinating article like yours. It is pretty value sufficient for me
4/4/2013 2:17 AM | click here
Gravatar

# re: CSS Scripting Layout Specification

Again, you can't connect the dots looking forward; you can only connect them looking backwards. So you have to trust that the dots will somehow connect in your future. You have to trust in something - your gut, destiny, life, karma, whatever. This approach has never let me down, and it has made all the difference in my life.
4/9/2013 2:49 AM | Advantages of fxopen
Gravatar

 re: CSS Scripting Layout Specification

i like ane useful
4/9/2013 4:06 AM | tamilarasan
Gravatar

# re: CSS Scripting Layout Specification

subsequent reference uses the result of the first evaluation. A reference is distinct on each child element on which the expression applies.
4/16/2013 3:48 AM | recover ipad data after reset
Gravatar

# re: CSS Scripting Layout Specification

I'm just in awe of this great post. The author is really incredibly talented. I admire this work of art.
4/18/2013 5:24 PM | government grant proposal
Gravatar

# hello

For the past 33 years, I have looked in the mirror every morning and asked myself: 'If today were the last day of my life, would I want to do what I am about to do today?' And whenever the answer has been 'No' for too many days in a row, I know I need to change something.
Migration Agent Melbourne
4/28/2013 10:03 AM | Migration Agent Melbourne
Gravatar

# re: CSS Scripting Layout Specification

I was really struck by the uniqueness of this post. I'm just in awe of its sophistication and originality. The author is actually an incredibly talented.
Gravatar

# re: CSS Scripting Layout Specification

The constraint resolver uses a set of heuristics to determine when to terminate. The primary heuristic is to stop when the last container size computation is a repeat of some prior computation, but only when all child rectangles’ sizes are at least as large as their preferred sizes, i.e. their content does not overextend their bounds. However, this second heuristic is relaxed in the case where all rectangle preferred sizes are a repeat of some prior computation. In this case, it is probably impossible to configure the child rectangles without some overextension.
5/12/2013 8:20 AM | supplements to build muscle

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 6 and 6 and type the answer here:
Home
Contact
RSS 2.0 Feed
Login
May, 2010 (1)
April, 2010 (1)
March, 2010 (1)
July, 2009 (1)
CSS Scripting Layout (rss)

Powered by: