Skip to content

Commit

Permalink
feat(layout-grid): parameterize layout grid (#795)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the css custom properties for customize margins and gutters are exposed in format of `mdc-layout-grid-margin-#{$size}`, where valid sizes are `desktop`, `tablet` and `phone`. The old name `mdc-layout-grid-margin` and `mdc-layout-grid-gutter` is no longer available in the new version. Sass variables change from single numeric value to Sass map to accomendate margins and gutters for different screens as well. Visually, the default value of margins and gutters change from 16px to 24px on desktop, while remain the same on tablet and mobile.
  • Loading branch information
yeelan0319 authored Jun 6, 2017
1 parent 0471f1f commit 99d2bbd
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 81 deletions.
115 changes: 89 additions & 26 deletions demos/layout-grid.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,28 +121,73 @@
</section>

<section class="examples">

<div class="demo-controls">
Margin:
<select id="margin">
<option value="8px">8px</option>
<option value="16px" selected>16px</option>
<option value="24px">24px</option>
<option value="40px">40px</option>
</select>

<br>

Gutter:
<select id="gutter">
<option value="8px">8px</option>
<option value="16px" selected>16px</option>
<option value="24px">24px</option>
<option value="40px">40px</option>
</select>
<div class="mdc-layout-grid">
<div class="mdc-layout-grid__cell">
<div class="demo-controls">
Desktop Margin:
<select id="desktop-margin">
<option value="8px">8px</option>
<option value="16px">16px</option>
<option value="24px" selected>24px</option>
<option value="40px">40px</option>
</select>

<br>

Desktop Gutter:
<select id="desktop-gutter">
<option value="8px">8px</option>
<option value="16px">16px</option>
<option value="24px" selected>24px</option>
<option value="40px">40px</option>
</select>
</div>
</div>
<div class="mdc-layout-grid__cell">
<div class="demo-controls">
Tablet Margin:
<select id="tablet-margin">
<option value="8px">8px</option>
<option value="16px" selected>16px</option>
<option value="24px">24px</option>
<option value="40px">40px</option>
</select>

<br>

Tablet Gutter:
<select id="tablet-gutter">
<option value="8px">8px</option>
<option value="16px" selected>16px</option>
<option value="24px">24px</option>
<option value="40px">40px</option>
</select>
</div>
</div>
<div class="mdc-layout-grid__cell">
<div class="demo-controls">
Phone Margin:
<select id="phone-margin">
<option value="8px">8px</option>
<option value="16px" selected>16px</option>
<option value="24px">24px</option>
<option value="40px">40px</option>
</select>

<br>

Phone Gutter:
<select id="phone-gutter">
<option value="8px">8px</option>
<option value="16px" selected>16px</option>
<option value="24px">24px</option>
<option value="40px">40px</option>
</select>
</div>
</div>
</div>
<div class="demo-warning"></div>

<div class="demo-warning"></div>

<div class="demo-grid-legend">Grid of 1 column wide items</div>
<div class="demo-grid mdc-layout-grid">
Expand Down Expand Up @@ -203,14 +248,32 @@
<script>
(function(global) {
'use strict';
var marginSelect = document.querySelector('#margin');
marginSelect.addEventListener('change', function() {
document.documentElement.style.setProperty('--mdc-layout-grid-margin', marginSelect.value);
var marginSelectDesktop = document.querySelector('#desktop-margin');
marginSelectDesktop.addEventListener('change', function() {
document.documentElement.style.setProperty('--mdc-layout-grid-margin-desktop', marginSelectDesktop.value);
});

var gutterSelectDesktop = document.querySelector('#desktop-gutter');
gutterSelectDesktop.addEventListener('change', function() {
document.documentElement.style.setProperty('--mdc-layout-grid-gutter-desktop', gutterSelectDesktop.value);
});
var marginSelectTablet = document.querySelector('#tablet-margin');
marginSelectTablet.addEventListener('change', function() {
document.documentElement.style.setProperty('--mdc-layout-grid-margin-tablet', marginSelectTablet.value);
});

var gutterSelectTablet = document.querySelector('#tablet-gutter');
gutterSelectTablet.addEventListener('change', function() {
document.documentElement.style.setProperty('--mdc-layout-grid-gutter-tablet', gutterSelectTablet.value);
});
var marginSelectPhone = document.querySelector('#phone-margin');
marginSelectPhone.addEventListener('change', function() {
document.documentElement.style.setProperty('--mdc-layout-grid-margin-phone', marginSelectPhone.value);
});

var gutterSelect = document.querySelector('#gutter');
gutterSelect.addEventListener('change', function() {
document.documentElement.style.setProperty('--mdc-layout-grid-gutter', gutterSelect.value);
var gutterSelectPhone = document.querySelector('#phone-gutter');
gutterSelectPhone.addEventListener('change', function() {
document.documentElement.style.setProperty('--mdc-layout-grid-gutter-phone', gutterSelectPhone.value);
});

var current = document.querySelector('#current');
Expand Down
61 changes: 36 additions & 25 deletions packages/mdc-layout-grid/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ there isn't enough room for a cell, it gets moved to the beginning of the next r
The grid has 12 columns in desktop mode (>= 840px), 8 columns in tablet mode (>= 480px), and 4 columns in phone mode
(< 480px). Column widths are variable; margins and gutters are fixed, with columns taking up the remainder of the space.

Margins (the space between the edge of the grid and the edge of the first cell) and gutters (the space between edges of
adjacent cells) are user-definable, with the Material Design spec recommending 8px, 16px, 24px or 40px as the sizes to
choose from. The default margin and gutter are both 16px, but they don't have to be the same size.
Margins (the space between the edge of the grid and the edge of the first cell) and gutters (the space between edges of adjacent cells) can be customized on different devices respectively based on design needs. Layout grids set default margins and gutters to 24px on desktop, 16px on tablet and phone, according to the Material Design spec.

The grid and cells are not styled in any way, serving only for alignment and positioning of elements.

Expand All @@ -70,24 +68,36 @@ Behavior for grids containing direct children without the `mdc-layout-grid__cell

### Margins and gutters

The default size for both the margins and gutters in MDC layout grid is 16px.
Layout grids set default margins and gutters to 24px on desktop, 16px on tablet and phone.

You can change the margins and gutters for a grid using the `--mdc-layout-grid-margin` and `--mdc-layout-grid-gutter`
custom properties, respectively. This requires support for CSS custom properties on the end-user's browser.
The Material Design spec recommends 8px, 16px, 24px or 40px as the sizes to choose from, we set those as choices in our demo catalog. However, MDC layout grid doesn't impose any restrictions.

The Material Design spec recommends 8px, 16px, 24px or 40px as the sizes to choose from, but MDC layout grid doesn't
impose any restrictions.
> Note: Due to the implementation of MDC layout grid, it's not possible to use a margin smaller than half of the size
of the gutter, in most browsers. As support for [CSS Grid](https://www.w3.org/TR/css-grid-1/) lands in browsers, this
limitation will go away, as MDC layout grid is progressively enhanced to support it.


#### CSS custom properties

You can change the margins and gutters for a grid using the `--mdc-layout-grid-margin-#{$device}` and `--mdc-layout-grid-gutter-#{$device}` custom properties, respectively. This requires support for CSS custom properties on the end-user's browser.

```css
.my-grid {
--mdc-layout-grid-margin: 40px;
--mdc-layout-grid-gutter: 16px;
--mdc-layout-grid-margin-desktop: 40px;
--mdc-layout-grid-gutter-tablet: 16px;
--mdc-layout-grid-gutter-phone: 8px;
}
```

> Note: Due to the implementation of MDC layout grid, it's not possible to use a margin smaller than half of the size
of the gutter, in most browsers. As support for [CSS Grid](https://www.w3.org/TR/css-grid-1/) lands in browsers, this
limitation will go away, as MDC layout grid is progressively enhanced to support it.
#### Sass variables

You can change the margins and gutters using sass variables if you are compiling from them. MDC layout grid uses sass map `mdc-layout-grid-default-margin` and `mdc-layout-grid-default-gutter` to define margins and gutters on different screen types.


### Max width

MDC layout grids take up the parent element space by default. However, user can set `$mdc-layout-grid-max-width` to restrict the max-width of the layout grid.


### Column spans

Expand All @@ -99,12 +109,10 @@ limitation will go away, as MDC layout grid is progressively enhanced to support
</div>
```

Cells have a default span size of 4 columns, with other sizes being possible by applying one of the span classes, of the
form `mdc-layout-grid__cell--span-{columns}`, where `{columns}` is an integer between 1 and 12.
You can set the cells span by applying one of the span classes, of the form `mdc-layout-grid__cell--span-{columns}`, where `{columns}` is an integer between 1 and 12. If the chosen span size is larger than the available number of columns at the current screen size, the cell behaves as if its chosen span size were equal to the available number of columns at that screen size. That is, it takes up the entirety of its row, and no more than that.

If the span classes are not set, `mdc-layout-grid__cell` will fallback to a default span size of 4 columns. You can make it a different number by changing the default value. However, this number needs to be provided at compile time by using sass variable `$mdc-layout-grid-default-column-span`.

If the chosen span size is larger than the available number of columns at the current screen size, the cell behaves as
if its chosen span size were equal to the available number of columns at that screen size. That is, it takes up the
entirety of its row, and no more than that.

### Column spans for specific screen sizes

Expand All @@ -126,6 +134,7 @@ In the example above, the first cell has a default span of 6, the second 4, and
the first cell becomes 8 columns wide instead, and the second 6 columns wide. At phone sizes, the third cell becomes 4
columns wide.


### Reordering

By default, items are positioned in the source order. However, you can reorder them by using the
Expand Down Expand Up @@ -162,26 +171,28 @@ behavior by using one of the `mdc-layout-grid__cell--align-{position}` alignment
### mdc-layout-grid

```scss
@include mdc-layout-grid(16px, 16px, 1600px);
@include mdc-layout-grid(desktop, 16px, 16px, 1600px);
```

`mdc-layout-grid` defines a grid and should be applied to the container element. The mixin takes three parameters:
`mdc-layout-grid` defines a grid and should be applied to the container element. The mixin takes four parameters:
- `$size`: the target platform: `desktop`, `tablet` or `phone`.
- `$margin`: the size of the grid margin.
- `$gutter`: the size of the gutter between cells.
- `$max-width` (optional): the maximum width of the grid, at which point space stops being distributed by the columns.

Note that the margin and gutter can be overriden at runtime by using the CSS custom properties detailed in the
"Margins and gutters" section under "CSS class usage".

### mdc-layout-grid-cell

```scss
@include mdc-layout-grid-cell(16px, 4);
@include mdc-layout-grid-cell(desktop, 4, 16px);
```

`mdc-layout-grid-cell` defines a cell and should be applied to the cell element. The mixin takes two parameters:
- `$size`: the target platform: `desktop`, `tablet` or `phone`.
- `$default-span` (optional, default 4): how many columns this cell should span (1 to 12).
- `$gutter`: the size of the gutter between cells. Be sure to use the same value as for the parent grid.
- `$span` (optional, default 4): how many columns this cell should span (1 to 12).

> Note even though size is passed in as one of the arguments, it won't apply any `media-query` rules. It is set for using the correct CSS custom properties to overriden the margin and gutter at runtime (See [Margins and gutters](#margins-and-gutters) section for detail).

### mdc-layout-grid-cell-order

Expand Down
36 changes: 12 additions & 24 deletions packages/mdc-layout-grid/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,61 +44,49 @@
}

width: calc(#{$percent} - #{$gutter});
width: calc(#{$percent} - var(--mdc-layout-grid-gutter, #{$gutter}));
width: calc(#{$percent} - var(--mdc-layout-grid-gutter-#{$size}, #{$gutter}));

@supports (display: grid) {
width: auto;
grid-column-end: span min($span, map-get($mdc-layout-grid-columns, $size));
}
}

@mixin mdc-layout-grid-cell-spans_($span, $gutter) {
@each $size in map-keys($mdc-layout-grid-columns) {
@include mdc-layout-grid-media-query_($size) {
@include mdc-layout-grid-cell-span_($size, $span, $gutter);
}
}
}

// Public mixins, meant for developer usage.
@mixin mdc-layout-grid($margin, $gutter, $max-width: null) {
@mixin mdc-layout-grid($size, $margin, $gutter, $max-width: null) {
display: flex;
flex-flow: row wrap;
align-items: stretch;
margin: 0 auto;
box-sizing: border-box;
padding: $margin - $gutter / 2;
padding: calc(var(--mdc-layout-grid-margin, #{$margin}) - var(--mdc-layout-grid-gutter, #{$gutter}) / 2);

@if $max-width {
max-width: $max-width;
}

padding: $margin - $gutter / 2;
padding: calc(var(--mdc-layout-grid-margin-#{$size}, #{$margin}) - var(--mdc-layout-grid-gutter-#{$size}, #{$gutter}) / 2);

@supports (display: grid) {
display: grid;
grid-gap: $gutter;
grid-gap: var(--mdc-layout-grid-gutter, $gutter);
grid-gap: var(--mdc-layout-grid-gutter-#{$size}, $gutter);
padding: $margin;
padding: var(--mdc-layout-grid-margin, #{$margin});

@each $size in map-keys($mdc-layout-grid-columns) {
@include mdc-layout-grid-media-query_($size) {
grid-template-columns: repeat(map-get($mdc-layout-grid-columns, $size), minmax(0, 1fr));
}
}
padding: var(--mdc-layout-grid-margin-#{$size}, #{$margin});
grid-template-columns: repeat(map-get($mdc-layout-grid-columns, $size), minmax(0, 1fr));
}
}

@mixin mdc-layout-grid-cell($gutter, $span: 4) {
margin: $gutter / 2;
margin: calc(var(--mdc-layout-grid-gutter, #{$gutter}) / 2);
@mixin mdc-layout-grid-cell($size, $default-span, $gutter) {
box-sizing: border-box;
margin: $gutter / 2;
margin: calc(var(--mdc-layout-grid-gutter-#{$size}, #{$gutter}) / 2);

@supports (display: grid) {
margin: 0;
}

@include mdc-layout-grid-cell-spans_($span, $gutter);
@include mdc-layout-grid-cell-span_($size, $default-span, $gutter);
}

@mixin mdc-layout-grid-cell-order($order) {
Expand Down
16 changes: 14 additions & 2 deletions packages/mdc-layout-grid/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ $mdc-layout-grid-columns: (
phone: 4
) !default;

$mdc-layout-grid-default-margin: (
desktop: 24px,
tablet: 16px,
phone: 16px
) !default;

$mdc-layout-grid-default-gutter: (
desktop: 24px,
tablet: 16px,
phone: 16px
) !default;

$mdc-layout-grid-default-column-span: 4 !default;
$mdc-layout-grid-default-margin: 16px !default;
$mdc-layout-grid-default-gutter: 16px !default;

$mdc-layout-grid-max-width: null;
24 changes: 20 additions & 4 deletions packages/mdc-layout-grid/mdc-layout-grid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,38 @@
@import "./variables";
@import "./mixins";

:root {
@each $size in map-keys($mdc-layout-grid-columns) {
--mdc-layout-grid-margin-#{$size}: map-get($mdc-layout-grid-default-margin, $size);
--mdc-layout-grid-gutter-#{$size}: map-get($mdc-layout-grid-default-gutter, $size);
}
}

// postcss-bem-linter: define layout-grid
.mdc-layout-grid {
@include mdc-layout-grid($mdc-layout-grid-default-margin, $mdc-layout-grid-default-gutter);
@each $size in map-keys($mdc-layout-grid-columns) {
@include mdc-layout-grid-media-query_($size) {
$margin: map-get($mdc-layout-grid-default-margin, $size);
$gutter: map-get($mdc-layout-grid-default-gutter, $size);

@include mdc-layout-grid($size, $margin, $gutter, $mdc-layout-grid-max-width);
}
}
}

.mdc-layout-grid__cell {
@include mdc-layout-grid-cell($mdc-layout-grid-default-gutter);

@each $size in map-keys($mdc-layout-grid-columns) {
@include mdc-layout-grid-media-query_($size) {
$gutter: map-get($mdc-layout-grid-default-gutter, $size);

@include mdc-layout-grid-cell($size, $mdc-layout-grid-default-column-span, $gutter);

@for $span from 1 through map-get($mdc-layout-grid-columns, desktop) {
// Span classes.
// stylelint-disable max-nesting-depth
@at-root .mdc-layout-grid__cell--span-#{$span},
.mdc-layout-grid__cell--span-#{$span}-#{$size}.mdc-layout-grid__cell--span-#{$span}-#{$size} {
@include mdc-layout-grid-cell-span_($size, $span, $mdc-layout-grid-default-gutter);
@include mdc-layout-grid-cell-span_($size, $span, $gutter);
}
// stylelint-enable max-nesting-depth
}
Expand Down

0 comments on commit 99d2bbd

Please sign in to comment.