The Right Layout Tool for the Job

Post on 23-Jan-2018

2.370 views 0 download

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: me@rachelandrew.co.uk

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 | me@rachelandrew.co.uk

https://rachelandrew.co.uk | https://grabaperch.com