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.
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:
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:
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.
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.
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:
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:
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.
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.
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.
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.
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:
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):
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:
These are functionally identical to the Template layout properties,
and likewise aren't implemented yet (and, of course, may never be).
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:
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:
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.
The 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.
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:
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:
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.
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.
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.
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.
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; }
- div { column-width: 140px; }
- div {
- column-gap: 28px;
- column-rule: 2px dotted #ccc;
- }
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; }
- .child-one { box-flex: 1; }
- .child-two { box-flex: 2; }
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;
- }
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: 100px auto 12em;
- }
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:
- header { grid-column: 1; grid-column-span: 3; grid-row: 1; }
- nav { grid-column: 1; grid-row: 2; }
- article { grid-column: 2; grid-row: 2; }
- aside { grid-column: 3; grid-row: 2; }
- footer { grid-column: 1; grid-column-span: 3; grid-row: 3; }
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.
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; }
- div { display: 'abc'; }
- div {
- display:
- 'baa'
- 'bcc';
- }
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';
- }
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:- div {
- float: positioned;
- left: 200px; position: absolute; top: 100px; width: 250px;
- }
- div { wrap-type: top-bottom; }
- div {
- float: positioned;
- grid-column: 2;
- grid-row: 2;
- }
The 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); }
- div { wrap-shape: polygon(0,100px 100px,100px 50px,0); }
- div {
- wrap-shape: circle(50%, 50%, 100px);
- wrap-shape-mode: around;
- }
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); }
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:
No comments: