The Right Layout Tool for the Job
-
Upload
rachel-andrew -
Category
Technology
-
view
2.370 -
download
0
Transcript of The Right Layout Tool for the Job
The Right Layout Tool for the Job.
Rachel Andrew, WebExpo, Prague 2016
Rachel Andrew
rachelandrew.co.uk
@rachelandrew
CSS Working Group Invited Expert
Google Developer Expert for Web Technologies
Co-founder Perch CMS: https://grabaperch.com
Contact: [email protected]
Modern CSS Layout?
• Floats
• Inline-block
• display: table
• Absolute & Relative positioning
• Frameworks … lots of frameworks
Our great hopes for layout
• Flexboxhttps://drafts.csswg.org/css-flexbox/
• CSS Grid Layouthttps://drafts.csswg.org/css-grid/
• Box Alignmenthttps://drafts.csswg.org/css-align/
Getting Flexible
The justify-content property is set to space-between.
The items at each end are placed against the container and the remaining space distributed evenly.
nav ul{ display: flex; justify-content: space-between; }
The justify-content property is set to space-around.
The items are evenly distributed in the container with a half size space at each end.
nav ul{ display: flex; justify-content: space-around; }
The flex property
• flex-grow - add space
• flex-shrink - remove space
• flex-basis - the initial size before any growing or shrinking
The initial width of our li is 300 pixels, however it can grow larger and shrink smaller than 300 pixels.
.wrapper { display: flex; } .wrapper li { flex: 1 1 300px; min-width: 1px; }
If the value of flex-grow is 0 the boxes cannot grow.
.wrapper { display: flex; } .wrapper li { flex: 0 1 300px; min-width: 1px; }
If the value of flex-shrink is 0 the boxes cannot shrink.
.wrapper { display: flex; } .wrapper li { flex: 1 0 300px; min-width: 1px; }
Setting flex-grow to 2 on the 3 item.
.wrapper li { flex: 1 1 300px; min-width: 1px; }
.wrapper li:nth-child(3) { flex-grow: 2; }
With flex-basis 0 all the available space is up for grabs and can be assigned according to the flex-grow value.
.wrapper li { flex: 1 1 0; min-width: 1px; }
.wrapper li:nth-child(3) { flex-grow: 2; }
http://madebymike.com.au/demos/flexbox-tester/
The wonderful world of ‘auto’
https://drafts.csswg.org/css-flexbox/#valdef-flex-basis-auto
“When specified on a flex item, the auto keyword retrieves the value of the main size property as the used flex-basis. If that value is itself auto, then the used value is content.”
The ‘main size’
For flex items:
if flex-direction is row, main size is width
if flex-direction is column, main size is height
flex-basis: auto
If the item has a main size then it will be used for the flex-basis value.
Otherwise, flex-basis is set to ‘content’.
The flex-basis for the items inside wrapper is auto.
The items have no main size and so the defaults to content.
.box { width: 600px; }
.wrapper { display: flex; }
.wrapper > div { flex: 1 1 auto; }
flex-basis: auto
I don’t need to change my CSS for the flex-basis to respect the component width.
.box { width: 600px; }
.wrapper { display: flex; }
.wrapper > div { flex: 1 1 auto; }
flex-basis: auto 600px
I want this bar aligned to the bottom
Making each card a flex container means we can use flexbox for the alignment.
/* the wrapper */ .inner { display: flex; }
/* the cards */ .card { flex: 1 1 0; display: flex; flex-direction: column; }
/* the stretching content */ .content { flex: 1 1 auto; }
flex: 1 1 300px;
flex-grow: 1 flex-shrink: 1; flex-basis: 300px;
If we allow the flex items to wrap we can see how flex-basis works by dragging the window smaller.
.wrapper { display: flex; flex-flow: row wrap; } .wrapper li { flex: 1 1 300px; min-width: 1px; }
flex: 1 1 300px;
flex-grow: 1; flex-shrink: 1; flex-basis: 300px;
The 3rd item has flex: 0 1 300px; so cannot grow.
.wrapper { display: flex; } .wrapper li { flex: 1 1 300px; min-width: 1px; }
.wrapper li:nth-child(3) { flex: 0 1 300px; }
CSS Grid Layout
I am creating three grid column tracks, all 1fr in width.
This gives me three equally sized column tracks.
.wrapper { display: grid; grid-template-columns: 1fr 1fr 1fr; }
If I create the first column as 600 pixels and then have two 1fr columns the 600 pixel track is removed from the available space and the remainder is distributed equally between the two columns.
.wrapper { display: grid; grid-template-columns: 600px 1fr 1fr; }
With a 600 pixel column, a 1fr and a 3fr column. The 600 pixels is removed from the available space then the remaining space is divided by 4.
The 1fr column gets 25% and the 3fr column 75%.
.wrapper { display: grid; grid-template-columns: 600px 1fr 3fr; }
Flexbox for 1 dimensional layout.
CSS Grid is for 2 dimensional layout.
repeat notation.
These two track listings are the same. .wrapper {
display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; }
.wrapper { display: grid; grid-template-columns: repeat(4, 1fr); }
minmax()
Declare a minimum and a maximum size for tracks.
.wrapper { display: grid; grid-auto-rows: minmax(200px, 400px); }
The value of the grid-template-columns property says:
repeat this track listing, auto-filing as many columns with a minimum width of 300 pixels and a maximum of 1fr.
.wrapper { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
Grid auto-placement
My grid auto-fills columns with a minimum width of 80px and a maximum width of 1fr.
The rows will also use minmax() to by at least 80px tall.
.colors { display: grid; grid-template-columns: repeat(auto-fill,minmax(80px, 1fr)); grid-gap: 2px; grid-auto-rows: minmax(80px, auto); }
Some items span 2 column tracks.
Some span 3 column tracks.
Some blocks are tall and span 4 row tracks.
.span2 { grid-column-end: span 2; grid-row-end: span 2; }
.span3 { grid-column-end: span 3; grid-row-end: span 3; }
.tall4 { grid-row-end: span 4; }
The grid-auto-flow property can be set to dense.
This enables a dense ‘packing mode’. .colors {
display: grid; grid-template-columns: repeat(auto-fill,minmax(80px, 1fr)); grid-gap: 2px; grid-auto-rows: minmax(80px, auto); grid-auto-flow: dense; }
Any items with a position on the grid are placed before auto-placed items.
.white { grid-column: 1 / -1; grid-row: 3; }
.black { grid-column: 1 / -1; grid-row: 6; }
Grid Item Placement
I have created a grid on my wrapper element. The grid has 3 equal width columns. Rows will be created as required as we position items into them.
.wrapper { display: grid; grid-template-columns: 1fr 1fr 1fr; }
The class ‘wrapper’ is on a ul element.
<ul class="wrapper"> <li class="one"> <h3>1.</h3> </li> <li class="two"> <h3>2.</h3> </li> <li class="three"> <h3>3.</h3> </li> <li class="four"> <h3>4.</h3> </li> <li class="five"> <h3>5.</h3> </li> </ul>
I am positioning my elements using CSS Grid Layout line-based positioning.
Setting a column and a row line using the grid-column and grid-row properties.
.one { grid-column: 1 / 3; grid-row: 2 / 4; }
.two { grid-column: 3; grid-row: 1 / 3; }
.three { grid-column: 3; grid-row: 3; }
.four { grid-column: 1; grid-row: 1 / 3; }
.five { grid-column: 2 / 4; grid-row: 1 ; }
Alignment
CSS Box Alignment Module Level 3
“This module contains the features of CSS relating to the alignment of boxes within their containers in the various CSS box layout models: block layout, table layout, flex layout, and grid layout.” - https://drafts.csswg.org/css-align/
It’s 2016. We can now centre things.
Box Alignment Properties- justify-content
- align-content
- justify-self
- align-self
- justify-items
- align-items
The justify-content property is set to space-between.
The items at each end are placed against the container and the remaining space distributed evenly.
nav ul{ display: flex; justify-content: space-between; flex-direction: row; }
The justify-content property is set to space-around.
The items are evenly distributed in the container with a half size space at each end.
nav ul{ display: flex; justify-content: space-around; flex-direction: row; }
If there is space in the grid container after all column and row tracks have been added.
Use space-around and space-between to space the tracks.
.wrapper { width: 500px; height: 400px; display: grid; grid-gap: 10px; grid-template-columns: repeat(4, 80px); grid-template-rows: repeat(3,100px); align-content: space-around; justify-content: space-between; }
The value of align-items is stretch by default.
If I add extra text in one navigation point the others all take the same height.
nav ul{ display: flex; justify-content: space-around; flex-direction: row; align-items: stretch; }
If I set the value of align-items to center then we get vertical centring.
nav ul{ display: flex; justify-content: space-around; flex-direction: row; align-items: center; }
My grid has an absolute width and height. This is larger than required for the tracks.
.wrapper { width: 500px; height: 400px; display: grid; grid-gap: 10px; grid-template-columns: repeat(4, 80px); grid-template-rows: repeat(3,100px); }
The align-content property controls the block axis.
This axis aligns the grid rows.
.wrapper { width: 500px; height: 400px; display: grid; grid-gap: 10px; grid-template-columns: repeat(4, 80px); grid-template-rows: repeat(3,100px); align-content: end; }
The justify-content property controls the inline axis.
This axis aligns the grid columns.
.wrapper { width: 500px; height: 400px; display: grid; grid-gap: 10px; grid-template-columns: repeat(4, 80px); grid-template-rows: repeat(3,100px); align-content: end; justify-content: center; }
I can create this same layout with flexbox or Grid.
With flexbox the items are laid out in a row.
.wrapper { display: flex; }
.wrapper li { flex: 1 0 25%; }
The first item is at the default stretch and as the tallest item is dictating the height of the flex container.
The second is entered in the container.
The third aligned to the start.
The fourth aligned to the end.
.wrapper li:nth-child(2) { align-self: center; }
.wrapper li:nth-child(3) { align-self: flex-start; }
.wrapper li:nth-child(4) { align-self: flex-end; }
For Grid I use a single row, 4 column Grid.
.wrapper { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; }
Grid alignment properties for the three landscape images.
.wrapper li:nth-child(2) { align-self: center; }
.wrapper li:nth-child(3) { align-self: start; }
.wrapper li:nth-child(4) { align-self: end; }
Putting it together: a form
100vh
body { align-content: center; justify-content: center;}
Aligning the grid.
body { height: 100vh; display: grid; grid-template-columns: 80%; align-content: center; justify-content: center; }
.account { align-self: end;}
1fr
1fr
1fr 1fr 1fr
2fr
2fr
.login > div
.login > div
.login > div.actions
Setting align-items to centre lines the fields and labels up on their centre line.
.login > div { display: grid; grid-template-columns: 1fr 2fr; align-items: center; }
.login > div.actions { grid-template-columns: 1fr 1fr 1fr; }
Hero Panels
Using the minmax() function with grid-auto-rows.
.home-hero { display: grid; grid-gap: 1px; grid-auto-rows: minmax(150px, auto); }
An item on the grid can become a grid or flex container itself.
In this case I am using flexbox and auto margins to push my content to the bottom of the box.
.special { display: flex; flex-direction: column; }
.special h3{ margin-top: auto; }
But, what about old browsers?!
http://caniuse.com/#feat=css-grid
http://caniuse.com/#feat=css-grid
http://gridbyexample.com/browsers
Say hello to Feature Queries.
I have set three classes to
display: none;
.has-flex,
.has-grid,
.has-grid-shapes { display: none; }
My @supports rule tests for support of the display property with a value of flex.
If it is supported we show the div.
@supports (display: flex) { .has-flex { display: block; } }
My @supports rule tests for support of the display property with a value of grid.
If it is supported we show the div.
@supports (display: grid) { .has-grid { display: block; } }
My @supports rule tests for support of the display property with a value of grid AND shape-outside:circle.
If it is supported we show the div.
@supports (display: grid) and (shape-outside:circle()) { .has-grid-shapes { display: block; } }
http://caniuse.com/#feat=css-featurequeries
Defaults for all browsers will be loaded by even really old browsers. body {
padding-top: 20%; }
h1, .login, .account, .contact{ width:80%; margin: 0 auto; }
Within a Feature Query we add some information for flexbox supporting browsers.
@supports (display: flex) { body { padding:0; height: 100vh; display: flex; align-items: center; justify-content: center; flex-direction: column; } h1, .login, .account, .contact { margin: 0; width: 80%; } }
The Feature Query for Grid supporting browsers.
@supports (display: grid) { body { display: grid; grid-template-columns: 80%; align-content: center; align-items: stretch; } @media (min-width: 650px) { body { grid-template-columns: repeat(2, minmax(150px, 30%)); } h1, .login { grid-column-end: span 2; width: auto; } .login > div { display: grid; grid-template-columns: 1fr 2fr; align-items: center; } .login > div.actions { grid-template-columns: 1fr 1fr 1fr; } .account { border-right: 1px dotted rgb(191, 216, 227); padding: 0 10px 0 0; align-self: end; width: auto; } .contact { padding: 0 0 0 10px; width: auto; } } }
Your users ‘grow into’ enhancements as their browsers
auto-update.
Accessibility
Power and responsibility
• Good = creating the most accessible source order and using Grid or Flexbox to get the optimal display for each device.
• Bad = using Grid or Flexbox as an excuse to forget about the source.
• Terrible - stripping out semantic elements to make everything a grid or flex item.
Léonie Watson | On CSS accessibility and drinking tea | CSS Day 2016
https://vimeo.com/180566024
Also see: http://tink.uk/flexbox-the-keyboard-navigation-disconnect/
https://drafts.csswg.org/css-grid/#order-accessibility
“Authors must use order and the grid-placement properties only for visual, not logical, reordering of content. Style sheets that use these features to perform logical reordering are non-conforming.”
Performance
https://jakearchibald.com/2014/dont-use-flexbox-for-page-layout/
https://blogs.igalia.com/jfernandez/2015/06/24/performance-on-grid-layout/
Why are we looking at something I can’t use yet?
https://wiki.csswg.org/ideas/mistakes
Get involved with developing specs!
• While a spec is being developed your feedback is wanted and can be included in the spec.
• Wait until browsers ship and you lose that chance.
• It just got easier. CSS Spec issues are now on GitHub.http://logs.csswg.org/irc.w3.org/css/2016-05-10/#e684439
Do a good deed for your future self.
Thank you
Slides & Resources: https://cssgrid.me/WebExpo16
http://csslayout.news - sign up for my weekly CSS Layout email
—
@rachelandrew | [email protected]
—
https://rachelandrew.co.uk | https://grabaperch.com