Tuesday, March 25, 2014

Microsoft 70-480: Create a flexible content layout

Exam Objectives


Implement a layout using a flexible box model; implement a layout using multi-column; implement a layout using position floating and exclusions; implement a layout using grid alignment; implement a layout using regions, grouping, and nesting


Quick Overview of Training Materials


Programming in HTML5 with JavaScript and CSS3 - Training Guide - Chapter 4
w3.org - CSS ExclusionsCSS Grid Layout, CSS Regions, CSS Flexible Box Layout

The flexbox layout is designed to allow child elements of the layout container (that is, the element with display: flex) to shrink, grow, and reposition themselves to best fill the available space without overflowing.  Children can be arranged vertically or horizontally, and it is possible to nest (flexboxes filled with flexboxes). The flexbox layout model has these key characteristics:

  • The flexbox container has a main axis and a cross axis. 
  • Flow direction is determined by the main axis and can be left, right, up, or down.
  • Elements can be displayed in reverse or rearranged order.
  • Flexbox children stretch and shrink according to available space
  • Their alignment is configurable
This figure from the spec illustrates the relationship of the axis to the flex container and flow direction
Flexboxes can be specified with either display: flex or display: inline-flex. Even though flex is obstensibly a block type display, some block properties do not have any effect in a flexbox layout: multicolumn, float & clear, vertical-align, and the ::first-line and ::first-letter pseudo-elements. Also, flexbox items with absolute positioning are not flexed.  

Most of the configuration of a flexbox is done with CSS properties on the flex container (from spec):
  • flex-flow - shorthand method (<flex-direction> || <flex-wrap>)
    • flex-direction - The direction items flow.  Can be right to left (row), left to right (row-reverse), top to bottom (column) or bottom to top (column-reverse) ... for English at least.
    • flex-wrap - determines if a flexbox is single line (nowrap) or multiline. Multiline flexboxes can from from top to bottom (wrap) or from bottom to top (wrap-reverse).
  • justify-content - aligns flex items along the main axis. Can align to the start, end, or center (flex-start, flex-end, and center, respectively), as well as being justified with uniform space all around (space-around), or just space between items with the first and last item adjoining the sides of the container (space-between).
  • align-items - aligns items in the cross axis. Flex-start and -end, and center are essentially the same; baseline aligns items according to the baseline of their text; stretch stretches or shrinks the element to match the flex-line as closely as possible while still respecting min/max height/width
  • align-content - aligns all the flexlines with respect to the flex container. Flex-start and -end, center, space-between and -around, and stretch all act similarly to the descriptions above, just with respect to whole lines rather than individual flex items.
There are several properties for flex items that impact how they behave in the flex box container:
  • flex - shorthand for grow, shrink, and basis
    • flex-grow - positive integer that sets the flex grow factor, which determines how much the item will grow to fill available space.
    • flex-shrink - positive integer that sets the flex shrink factor, which determines how much the item will shrink when free space is negative.
    • flex-basis - positive integer that sets the flex basis, which is the initial main size of the flex item.
  • align-self - overrides the "align-items" property for the individual item. Same arguements with the addition of "auto", which computes to the value of align-items of the parent or "stretch" if there is not parent.
JSFiddle demo of flexbox, add boxes using the button to get multiple lines. You'll need a newer browser (IE11; Current Chrome, FF, Opera, Safari):


Grid Layout


Grid layout aims to divide up large regions of space into rows and columns. While they are similar to tables, they do not define content structure.  Because content is not structured, grid items can be dynamically rearraged according to media queries. Grid rows and columns (called "tracks" in the spec) are specified (in IE) using the grid-rows and grid-columns CSS properties on the grid container (using -ms prefix). In the spec the properties are called grid-template-columns and grid-template-rows. The tracks are specified by supplying whichever property a list of dimensions.

While some of these dimensions are easy enough to recognize (px, %), there are new ways to specify these lengths as well. The fr unit represents a fraction of the available space (called a "flex length"). This unit divides up the available free space in proportion to the fr of each unit being allocated; if two units are being allocated free space and one is specified 1fr and the other 2fr, the second item will get twice as much space allocated as the first.

One strategy the spec illustrates is to specify some fixed columns and rows in px (or use auto), and then use the minmax() function to allocate the rest, usually something like minmax(min-content, 1fr), which says the minimum size for the track is the minimum size for the content, and the max is to take up the whole fraction of left over space.

Exclusions go hand in hand with the grid layout, and effectively define an area that other content should flow around.  The exclusion is defined at defining the grid position for the excluded element and setting the CSS property wrap-flow to correspond to how content should flow. Specifying both wraps content to either side of the exclusion, specifying start or end will keep content on only one side of the exclusion. Maximum wraps to the bigger side, and clear keeps content out of the side area.

Honestly, because this spec is still in working draft and there is almost no support, I can't see going into any more depth on Grid Layout. Maybe by the time I'm ready to retest it will be better supported...

Currently Grid Layout is only supported in IE10+, so I had to (begrudgingly) use IE to write this JSFiddle demo (but you'll have to use IE to see it, so there!).  If you don't want to deal with IE, here is what it looks like:
Added some random boxes to the grid....

Those same boxes after the grid is 50% smaller in either direction.

And the demo for you IE users:


Multicolumn Layout


Using multicolumn layout is relatively simple. The following CSS properties can be used to define a multicolumn layout:
  • columns - shorthand for the following two properties
    • column-count - sets an arbitrary number of columns, column width is automatic
    • column-width - minimum column width, new columns created automatically
  • column-gap - amount of space between columns
That really is all there is to it. Column height is unrestained, so set min-height or height to limit (though this would probably lead to overflow so I'm not sure why MozDN says to do this...).  By way of a demo:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis eu arcu at lorem pellentesque ornare. Sed dui sapien, lacinia quis malesuada in, gravida id neque. Ut viverra consectetur sagittis. Curabitur non tellus vel turpis adipiscing ullamcorper. Integer blandit malesuada viverra. Nunc vel urna velit. Aenean lacinia enim sed nibh tempor vestibulum. Nam ut velit lacus. Quisque congue diam non odio ultricies bibendum. Maecenas ut elit semper, vulputate velit ac, interdum lectus. Proin pellentesque iaculis nisi eu lobortis. Nam a ligula laoreet, rhoncus magna sed, dignissim massa. Mauris quis nibh pretium mauris iaculis porta.


Regions Layout


Regions are supported in IE10+ and new versions of Safari. The idea behind regions is that content will "flow" from one container to another. I couldn't get any of the demos I found to work right, and there seems to be disagreement within the web development community regarding whether this is really a good idea. This is another thing I can't see spending a lot of time on until it is more widely adopted.

Going off the spec, the way regions work is by created a "named flow" into which content is loaded from a source (that source being a specified DOM element). Content from this named flow can then be loaded into regions:

  • flow-into - this property loads content into the "named flow". Content is loaded according to document order (when loading from multiple sources).  If we had a <div> with id "source", we might specify to load it into the named flow called "name":
         #source{
              flow-into: name;
         }
  • flow-from - this designates the regions into which to flow the content from a named flow.  Like flow-into, data is loading into the regions accourding to document order.  If we hand three regions with the class "region" we might specify:
         .region{
              flow-from: name;
         }
  • break-before, -after, -inside - controls column and page breaks. Extends page-break-before, -after, -inside from the multicolumn spec.
  • region-fragment - controls the behavior of the last region associated with a named flow. If set to break, the content will stop flowing in (as if there were another region to go to). If set to auto, if will all go to the last region and overflow if it doesn't fit.

Scratch that, I did finally find a working demo. Weirdly, the same code doesn't work in JSFiddle in the same browser...

No comments:

Post a Comment