diff --git a/app/material-styleguide.html b/app/material-styleguide.html
index a7e0fbcf..153b3f4d 100644
--- a/app/material-styleguide.html
+++ b/app/material-styleguide.html
@@ -115,6 +115,11 @@
Header panel
+
+
+
Column Layout
+
+
diff --git a/app/styleguide/column-layout/_column-layout.scss b/app/styleguide/column-layout/_column-layout.scss
new file mode 100644
index 00000000..1a4bbaca
--- /dev/null
+++ b/app/styleguide/column-layout/_column-layout.scss
@@ -0,0 +1,97 @@
+/* Cutoff points for devices */
+$min_tablet_size: 768px;
+$min_desktop_size: 1024px;
+
+/* Web (desktop) layout. Columns are fixed width, and there's a maximum number
+ of 3 columns, after which we just add padding to either side. */
+$web_columns: 3;
+$web_column_size: 360px;
+$web_gutter: 40px;
+
+/* Tablet layout. There's a fixed number of columns, which grow to fill the
+ entire container. */
+$tablet_columns: 2;
+$tablet_gutter: 24px;
+
+/* Phone layout. There's a fixed number of columns, which grow to fill the
+ entire container. */
+$phone_columns: 1;
+$phone_gutter: 16px;
+
+
+/* Web layout */
+.column-layout {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: center;
+
+ margin: 0;
+ box-sizing: border-box;
+ padding: $web_gutter / 2;
+}
+
+.column-layout > * {
+ min-width: $web_column_size;
+ width: $web_column_size;
+ margin: $web_gutter / 2;
+ box-sizing: border-box;
+}
+
+/* Alright, this is not pretty, but we need to add a number of invisible
+ elements to make sure that the flexbox elements align properly, even when
+ wrapping to less than 3 columns. It's the only way I've found to get the
+ last line to align correctly, while keeping the flexbox centered on its
+ container.
+ TODO(sgomes): Explore a different way of doing this. */
+.column-layout > .wrap-hack {
+ height: 0;
+ min-height: 0;
+ max-height: 0;
+ border: none;
+ padding: 0;
+ margin-bottom: 0;
+ margin-top: 0;
+}
+
+/* Add padding to avoid the flexbox growing beyond 3 columns.
+ Yes, we use padding with calc. I promise this is the last hack. */
+$web_block_size: $web_column_size + $web_gutter;
+$web_padding_size: $web_columns * ($web_column_size + $web_gutter) / 2;
+@media screen
+ and (min-width: ($web_columns + 1) * $web_block_size) {
+ .column-layout {
+ padding-left: calc(50% - #{$web_padding_size});
+ padding-right: calc(50% - #{$web_padding_size});
+ }
+}
+
+/* Tablet layout */
+$tablet_column_percent: 100% / $tablet_columns;
+@media screen
+ and (min-width: $min_tablet_size)
+ and (max-width: $min_desktop_size - 1px) {
+ .column-layout {
+ padding: $tablet_gutter / 2;
+ }
+
+ .column-layout > * {
+ margin: $tablet_gutter / 2;
+ min-width: calc(#{$tablet_column_percent} - #{$tablet_gutter});
+ width: calc(#{$tablet_column_percent} - #{$tablet_gutter});
+ }
+}
+
+/* Phone layout */
+$phone_column_percent: 100% / $phone_columns;
+@media screen and (max-width: $min_tablet_size - 1px) {
+ .column-layout {
+ padding: $phone_gutter / 2;
+ }
+
+ .column-layout > * {
+ margin: $phone_gutter / 2;
+ width: calc(#{$phone_column_percent} - #{$phone_gutter});
+ min-width: calc(#{$phone_column_percent} - #{$phone_gutter});
+ }
+}
diff --git a/app/styleguide/column-layout/column-layout.js b/app/styleguide/column-layout/column-layout.js
new file mode 100644
index 00000000..d3f2ad45
--- /dev/null
+++ b/app/styleguide/column-layout/column-layout.js
@@ -0,0 +1,20 @@
+'use strict';
+
+(function() {
+ window.addEventListener('load', function() {
+ var INVISIBLE_WRAPPING_ELEMENT_CLASS = 'wrap-hack';
+ var INVISIBLE_WRAPPING_ELEMENT_COUNT = 3;
+ var columnLayouts = document.querySelectorAll('.column-layout');
+
+ for (var i = 0; i < columnLayouts.length; i++) {
+ var columnLayout = columnLayouts[i];
+ // Add some hidden elements to make sure everything aligns correctly. See
+ // CSS file for details.
+ for (var j = 0; j < INVISIBLE_WRAPPING_ELEMENT_COUNT; j++) {
+ var hiddenHackDiv = document.createElement('div');
+ hiddenHackDiv.classList.add(INVISIBLE_WRAPPING_ELEMENT_CLASS);
+ columnLayout.appendChild(hiddenHackDiv);
+ }
+ }
+ });
+})();
diff --git a/app/styleguide/column-layout/demo.html b/app/styleguide/column-layout/demo.html
new file mode 100644
index 00000000..41999eba
--- /dev/null
+++ b/app/styleguide/column-layout/demo.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+ Column Layout
+
+
+
+
+
+
+
+
Each child
+
gets to be
+
an independent entity
+
to be placed in columns,
+
automatically.
+
+
+
+
diff --git a/app/styleguide/column-layout/demo.scss b/app/styleguide/column-layout/demo.scss
new file mode 100644
index 00000000..7fe7c39e
--- /dev/null
+++ b/app/styleguide/column-layout/demo.scss
@@ -0,0 +1,21 @@
+@import '../styleguide_demo_bp';
+@import '../palette/palette';
+@import '_column-layout';
+
+.column-layout {
+ background-color: nth($paletteGrey, 2);
+}
+
+.column-layout > * {
+ min-height: 300px;
+ background-color: nth($paletteGreen, 2);
+ padding: 16px;
+}
+
+.column-layout > *:nth-of-type(3n+1) {
+ background-color: nth($paletteRed, 2);
+}
+
+.column-layout > *:nth-of-type(3n+2) {
+ background-color: nth($paletteBlue, 2);
+}