After years of promise, CSS3 has finally arrived in style (if you'll
pardon the pun). It's added a whole new array of tools to our front-end
toolbox, giving us rounded corners, gradients, opacity, transformations,
transitions, animations and much more. But now that we have the fun
stuff, the eye candy, what's next?
The next problem for CSS3 to address will be layouts. Until now we've
got by with floats, relative positioning and negative margin tricks,
but we still have to work incredibly hard to produce anything beyond the
fairly standard two- to three-column layouts.
The W3C and the browser makers are aware of this problem, and working
on a range of solutions. Chief among them (you may be surprised to
learn) is the Internet Explorer team. IE10 looks set to herald an
exciting new era of CSS layouts, making possible rich, dynamic and
eye-catching websites that were previously beyond our reach.
In this article I'm going to take a look at the various layout
methods that are at different stages of development, from the
well-implemented to the purely theoretical. Perhaps not all of these
will make it to the stage where we're able to use them (or, at least,
not in their current form), but it's worth taking a look to see where
the future lies. If you want more detail about some of the methods in
this article, as well as much more of what CSS3 offers, I humbly
recommend my book, The Book of CSS3.
Columns
Distributing content over multiple columns is a staple of print, and the CSS Multi-Columns module
brings the same flexibility to the web. There are two approaches to
making columns, both of which use a different property (applied to the
parent element). The first is prescriptive, where you
explicitly set a number of columns to flow the text into. The following
code creates three columns of equal width, filling the width of the
parent:
div { column-count:3;}
The second system is dynamic, where the width of the columns
is fixed and columns of this width will be repeated until they match
the width of the parent. In this example I'll set the columns' width to
140px, so in a parent element 800px wide there should be five columns
created:
div { column-width:140px;}
By default there is a 1em gap between each column, but you can change this by using the column-gap property, which takes a length value. You can also put lines between the columns with column-rule,
which has the same syntax as the border properties. This code will
generate a dotted divider 2px wide, and set the gap to 28px – this will
be divided equally on either side of the rule:
div {
column-gap:28px;
column-rule:2pxdotted#ccc;
}
If you want to see the result, take a look at this example of CSS Columns. You'll need to be using Firefox, Chrome, Safari, Opera 11.1, or IE10 Platform Preview ('IE10PP') to view it; if you don't have one of those, see the image below for reference. CSS Columns provides an easy way to distribute long blocks of content into a more compact horizontal space
There's more you can do with columns, but space forbids. If you want
to see a practical example of their use, take a look at the References section of a Wikipedia article, which uses column-count to divide the notes into three columns. Multi-column is implemented in Firefox with the -moz- prefix (and some oddities), Chrome and Safari with the -webkit- prefix, and Opera 11.1+ and IE10PP, unprefixed.
Flexible box
The Flexible Box Layout module ('FlexBox')
provides a method of automatically resizing elements within their
parent without having to calculate height and width values. As a simple
example, imagine you have two child elements and you want them to fill
their parent (which has a variable width) in such a way that both have
the same width. You could do this with percentages, but it gets
complicated when borders, padding and margins are involved. The FlexBox
solution is much simpler:
.parent{display: box;}
.child-one,.child-two{ box-flex:1;}
That simply places the two child elements horizontally within their parent, and makes each the same width. The box-flex
value actually acts as a ratio, taking empty space and redistributing
it between child elements in the proportion of that value; to illustrate
what I mean, take a look at this code:
.child-one{ box-flex:1;}
.child-two{ box-flex:2;}
When the two elements are being distributed within their parent, .child-two's width would be increased by two pixels for every one of .child-one's; so if their parent was 260px wide and each child was 100px wide, the remaining 60px would be distributed 40px to .child-two, 20px to .child-one.
This is an easier concept to show than to explain, so you can see it more clearly in this example of CSS FlexBox (you'll need Firefox, Chrome, Safari, or IE10PP). Try resizing the browser window to see it scale.
As well as dynamically changing an element's size, FlexBox can also
apply properties to a parent that control where any empty space is
distributed, setting the position of its children. The box-align property acts on a child element's width (by default, although that can be changed), and there's a companion property, box-pack, that acts on its height. Here's how it works:
.parent{
box-align:center;
box-pack:center;
display: box;
height:200px;width:100px;
}
.child{
box-flex:0;
height:100px;width:100px;
}
The .child element has a box-flex
value of 0 so it won't be dynamically resized, and it's half the height
and width of its parent. The parent has the value 'center' for its box-align and box-pack properties, so the child will be positioned in the centre both horizontally and vertically. We showed how to make layouts with FlexBox in more detail in a previous article
You can read more about FlexBox in the .net magazine article The CSS3 Flexible Box model explained. It's currently implemented in Firefox, Chrome, Safari and IE10PP, with the relevant browser prefixes (-moz-,-webkit-, and -ms-), and there's a JS Polyfill, Flexie, you can experiment with. Be aware that the syntax is changing; details are in the latest draft of the specification.
Grid
Brand new to IE10PP is the Grid Layout
system, which I'm quite excited about. The first step to using it is to
define your grid with rows and columns. You can use length values, the auto keyword, and a new length unit, fr, which is shorthand for 'fraction'. Take a look at this code example:
div {
display: grid;
grid-columns: 1fr 3fr 1fr;
grid-rows:100pxauto12em;
}
This will create a grid of three columns, where the central column is
three times the width of the left and right columns, and three rows,
where the top row is 100px high, the bottom row is 12em high, and the
middle row expands automatically to fit its content.
Now that we have our grid, we can position content on it. Using HTML5
sectioning elements I can create a really simple common page layout:
Looking at that code you should be able to see that I place elements in columns and rows using, respectively, the grid-column and grid-row properties; in the case of the article element, I've positioned it in column 2, row 2 – the very centre of my 3x3 grid. I've also used column-span for the header and footer elements, making them span all three columns (there's a similar row-span property, which I haven't used here).
I've made an demo of a layout using these elements, which you can see in this example of CSS Grid Layout,
but you'll have to use the IE10 Platform Preview to see it. If you
don't have access to IE10PP, you can see it in this screenshot. A pretty standard three-column grid layout, built using CSS Grid properties only
The properties I've mentioned are all implemented in IE10PP, so you
can start to experiment with them right now. There are more properties
in the specification that are yet to be implemented (more on that
shortly), so that's something to look forward to.
Template
Another approach to grid systems is provided by the Template Layout module.
This uses a somewhat different syntax, the first step of which is
assigning position values using an alphabetical character and the position property:
header {position: a;}
nav {position: b;}
article {position: c;}
Once we've assigned positions, we can make layouts by using a string
of characters; each string equals a row, and each character in that
string, a column; for example, to make a grid of one row with three
columns, you would use:
div {display:'abc';}
This would display the three elements in a horizontal row, equally
distributed. But you can also repeat characters to span columns, and use
characters in the same position in different strings to span rows. In
the following example the nav element spans two rows, and the header and article each span two columns (I've formatted the code to make it easier to see):
div {
display:
'baa'
'bcc';
}
The Template Layout isn't currently implemented in any browser, but there's an excellent jQuery polyfill by Alexis Deveria that will let you experiment. I've used it in this example website using CSS Template properties. It looks identical to the demo I used for Grid Layout, but the underlying code is completely different.
The demo uses JavaScript so should work in most modern browsers, but
if you can't see it just take a look at the picture from the Grid Layout
section – it's exactly the same! Also, remember I said that there’s
more to come from the Grid Layout module? That includes properties which
adopt the Template syntax, as in this example:
header { grid-cell: a;}
article { grid-cell: b;}
div {
display: grid;
grid-template:'a''b';
}
These are functionally identical to the Template layout properties,
and likewise aren't implemented yet (and, of course, may never be).
Positioned floats
The current float property let's us float text around an element to either the left or right, but an extended property in IE10PP
lets us take that a step further and means that we can position the
floated element wherever we like, and the rest of its sibling content
will still flow around it. All that's required is a new value for float, and some positioning properties:
This will create an element that's 250px wide, positioned 200px from
the left and 100px from the top of its parent container. By default any
other content within the parent will flow around the positioned element
on all sides, but you can change that with different values for the wrap-type property, such as this one which flows the text only above and below the element:
div { wrap-type: top-bottom;}
You can also combine Positioned Floats with the Grid Layout module,
assigning the element a place within the grid and wrapping other content
around it:
div {
float: positioned;
grid-column:2;
grid-row:2;
}
Positioned Floats are implemented in IE10PP so you can start
experimenting right away, and if you have access to IE10PP you can see a
demo of CSS Positioned Floats combined with a Grid Layout and Multi-columns! If not, you can see in the image below a layout which is simply not possible using current CSS. A new style of layout only possible with new CSS properties, including Positioned FloatsThe Floats and Positioning specification
actually goes beyond what I've shown here, with more properties
including shaped floats, or floats made with image masks; these are not
currently in any browser, but see the next section for more on this.
Exclusions
So Positioned Floats allow you to flow content around a box-shaped element, but I mentioned that the specification also covers shaped floats. This idea comes from a module proposed by Adobe: CSS Exclusions. There are two key properties in this module; the first, wrap-shape, allows you to create ellipses, rectangles or polygons, which will dictate the form of the content flow; for example:
div { wrap-shape:circle(50%,50%,100px);}
This will create a circle with a radius of 100px, with its centre in the very centre of its parent. You can use the polygon() function to create any shape you like, using space-separated co-ordinate pairs, such as this triangle:
div { wrap-shape: polygon(0,100px100px,100px50px,0);}
When you have your shape, you can flow inline content (within the same parent element) around it using the second property, wrap-shape-mode, like so:
div {
wrap-shape:circle(50%,50%,100px);
wrap-shape-mode: around;
}
You can see CSS Exclusions in action by downloading a Prototype for Mac or Windows from Adobe Labs; this contains full documentation and some very impressive demo files, including the one shown in the image below. The text flows around the shape of the image thanks to CSS Exclusions
So as mentioned previously, the Exclusions syntax has been suggested
to be adopted into the Floats module, and so may possibly be implemented
as a subset of that rather than on its own.
Regions
A further suggestion by Adobe, CSS Regions,
provide a way of flowing content across multiple different elements.
This is done by first declaring the element from which the content will
be supplied, using a unique string value identifier with the flow property, then selecting which regions to flow that content through with the from() function on the content property:
.content{ flow: foo;}
.target1,.target2{content: from(foo);}
Quite simply, this takes the content from the element with the class of .content, then puts it first into the element .target1 and, if the content overflows, continues it in .target2.
To be clear, it doesn't duplicate the content in both targets, it
begins in the first and continues in the second (if required). To see
what I mean, take a look at the image below. Content from an element (not shown) flowing across three different elements, using CSS Regions
By the way, there's no requirement for the two target regions to
follow each other in the DOM or the layout; they can be on opposite
sides of the page, if necessary (although that may cause accessibility
issues).
The Regions spec isn't implemented in any browsers as yet but, as with Exclusions, you can download the prototype for from Adobe Labs and try it out for yourself.
CSS layouts : future
Reviewed by JohnBlogger
on
6:13 PM
Rating: 5
No comments: