diff --git a/core/modules/grid/config/grid.fluid_12.yml b/core/modules/grid/config/grid.fluid_12.yml
new file mode 100644
index 0000000..774b630
--- /dev/null
+++ b/core/modules/grid/config/grid.fluid_12.yml
@@ -0,0 +1,9 @@
+id: fluid_12
+label: Twelve column fluid
+type: equal_column
+options:
+  units: '%'
+  width: 100
+  columns: 12
+  padding_width: 1.5
+  gutter_width: 2
diff --git a/core/modules/grid/config/grid.fluid_3.yml b/core/modules/grid/config/grid.fluid_3.yml
new file mode 100644
index 0000000..7e6a9a6
--- /dev/null
+++ b/core/modules/grid/config/grid.fluid_3.yml
@@ -0,0 +1,9 @@
+id: fluid_3
+label: Three column fluid
+type: equal_column
+options:
+  units: '%'
+  width: 100
+  columns: 3
+  padding_width: 1.5
+  gutter_width: 2
diff --git a/core/modules/grid/config/grid.fluid_6.yml b/core/modules/grid/config/grid.fluid_6.yml
new file mode 100644
index 0000000..1d7fbcb
--- /dev/null
+++ b/core/modules/grid/config/grid.fluid_6.yml
@@ -0,0 +1,9 @@
+id: fluid_6
+label: Six column fluid
+type: equal_column
+options:
+  units: '%'
+  width: 100
+  columns: 6
+  padding_width: 1.5
+  gutter_width: 2
diff --git a/core/modules/grid/config/grid.ninesixty_12.yml b/core/modules/grid/config/grid.ninesixty_12.yml
new file mode 100644
index 0000000..5409789
--- /dev/null
+++ b/core/modules/grid/config/grid.ninesixty_12.yml
@@ -0,0 +1,9 @@
+id: ninesixty_12
+label: '960px wide, 12 column grid'
+type: equal_column
+options:
+  units: 'px'
+  width: 960
+  columns: 12
+  padding_width: 20
+  gutter_width: 10
diff --git a/core/modules/grid/config/grid.ninesixty_16.yml b/core/modules/grid/config/grid.ninesixty_16.yml
new file mode 100644
index 0000000..2cd9c65
--- /dev/null
+++ b/core/modules/grid/config/grid.ninesixty_16.yml
@@ -0,0 +1,9 @@
+id: ninesixty_16
+label: '960px wide, 16 column grid'
+type: equal_column
+options:
+  units: 'px'
+  width: 960
+  columns: 16
+  padding_width: 20
+  gutter_width: 10
diff --git a/core/modules/grid/grid.admin.inc b/core/modules/grid/grid.admin.inc
new file mode 100644
index 0000000..b71c511
--- /dev/null
+++ b/core/modules/grid/grid.admin.inc
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Administration functions to maintain a common set of grids.
+ */
+
+use Drupal\grid\Plugin\Core\Entity\Grid;
+
+/**
+ * Page callback: Presents list of grids.
+ *
+ * @see grid_menu()
+ */
+function grid_page_list() {
+  $controller = entity_list_controller('grid');
+  return $controller->render();
+}
+
+/**
+ * Page callback: Presents the grid editing form.
+ *
+ * @see grid_menu()
+ */
+function grid_page_edit(Grid $grid) {
+  drupal_set_title(t('<em>Edit grid</em> @label', array('@label' => $grid->label())), PASS_THROUGH);
+  return entity_get_form($grid);
+}
+
+/**
+ * Page callback: Provides the new grid addition form.
+ *
+ * @see grid_menu()
+ */
+function grid_page_add() {
+  $grid = entity_create('grid', array());
+  return entity_get_form($grid);
+}
+
+/**
+ * Page callback: Form constructor for grid deletion confirmation form.
+ *
+ * @see grid_menu()
+ */
+function grid_confirm_delete($form, &$form_state, Grid $grid) {
+  // Always provide entity id in the same form key as in the entity edit form.
+  $form['id'] = array('#type' => 'value', '#value' => $grid->id());
+  $form_state['grid'] = $grid;
+  return confirm_form($form,
+    t('Are you sure you want to remove the grid %title?', array('%title' => $grid->label())),
+    'admin/structure/grids',
+    t('This action cannot be undone.'),
+    t('Delete'),
+    t('Cancel')
+  );
+}
+
+/**
+ * Form submission handler for grid_confirm_delete().
+ */
+function grid_confirm_delete_submit($form, &$form_state) {
+  $grid = $form_state['grid'];
+  $grid->delete();
+  drupal_set_message(t('Grid %label has been deleted.', array('%label' => $grid->label())));
+  watchdog('grid', 'Grid %label has been deleted.', array('%label' => $grid->label()), WATCHDOG_NOTICE);
+  $form_state['redirect'] = 'admin/structure/grids';
+}
diff --git a/core/modules/grid/grid.info b/core/modules/grid/grid.info
new file mode 100644
index 0000000..9dd6db4
--- /dev/null
+++ b/core/modules/grid/grid.info
@@ -0,0 +1,8 @@
+name = Grid
+description = Pluggable grid system manager.
+package = Core
+version = VERSION
+core = 8.x
+dependencies[] = config
+configure = admin/structure/grids
+
diff --git a/core/modules/grid/grid.module b/core/modules/grid/grid.module
new file mode 100644
index 0000000..4ec1e0b
--- /dev/null
+++ b/core/modules/grid/grid.module
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Pluggable grid system manager module.
+ */
+
+use Drupal\grid\Plugin\Core\Entity\Grid;
+
+/**
+ * Implements hook_help().
+ */
+function grid_help($path, $arg) {
+  switch($path) {
+    case 'admin/help#grid':
+      return '<p>' . t('Grids provide useful guides to place content on your pages. The grid module provides the ability to edit any type of grid and supports fluid and fixed equal column grids by itself. Extend with contributed modules for more grid types.') . '</p>';
+  }
+}
+
+/**
+ * Implements hook_menu().
+ */
+function grid_menu() {
+  $items['admin/structure/grids'] = array(
+    'title' => 'Grids',
+    'description' => 'Manage list of grids which can be used with layouts.',
+    'page callback' => 'grid_page_list',
+    'access callback' => 'user_access',
+    'access arguments' => array('administer grids'),
+    'file' => 'grid.admin.inc',
+  );
+  $items['admin/structure/grids/add'] = array(
+    'title' => 'Add grid',
+    'page callback' => 'grid_page_add',
+    'access callback' => 'user_access',
+    'access arguments' => array('administer grids'),
+    'type' => MENU_LOCAL_ACTION,
+    'file' => 'grid.admin.inc',
+  );
+  $items['admin/structure/grids/manage/%grid'] = array(
+    'title' => 'Edit grid',
+    'page callback' => 'grid_page_edit',
+    'page arguments' => array(4),
+    'access callback' => 'user_access',
+    'access arguments' => array('administer grids'),
+    'type' => MENU_CALLBACK,
+    'file' => 'grid.admin.inc',
+  );
+  $items['admin/structure/grids/manage/%grid/edit'] = array(
+    'title' => 'Edit',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+  $items['admin/structure/grids/grid/%grid/delete'] = array(
+    'title' => 'Delete',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('grid_confirm_delete', 4),
+    'access callback' => 'user_access',
+    'access arguments' => array('administer grids'),
+    'type' => MENU_LOCAL_TASK,
+    'file' => 'grid.admin.inc',
+  );
+  return $items;
+}
+
+/**
+ * Implements hook_permission().
+ */
+function grid_permission() {
+  return array(
+    'administer grids' => array(
+      'title' => t('Administer grids'),
+      'description' => t('Administer grids created with the grid module.'),
+    ),
+  );
+}
+
+/**
+ * Entity URI callback.
+ *
+ * @param Drupal\grid\Grid $grid
+ *   Grid configuration entity instance.
+ *
+ * @return array
+ *   Entity URI information.
+ */
+function grid_uri(Grid $grid) {
+  return array(
+    'path' => 'admin/structure/grids/manage/' . $grid->id(),
+  );
+}
+
+/**
+ * Look up one grid setup based on machine name.
+ *
+ * @return Drupal\grid\Grid
+ *   Grid configuration entity instance.
+ */
+function grid_load($id) {
+  return entity_load('grid', $id);
+}
diff --git a/core/modules/grid/lib/Drupal/grid/GridBundle.php b/core/modules/grid/lib/Drupal/grid/GridBundle.php
new file mode 100644
index 0000000..eb5b927
--- /dev/null
+++ b/core/modules/grid/lib/Drupal/grid/GridBundle.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\grid\GridBundle.
+ */
+
+namespace Drupal\grid;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * Grid dependency injection container.
+ */
+class GridBundle extends Bundle {
+
+  /**
+   * Overrides Symfony\Component\HttpKernel\Bundle\Bundle::build().
+   */
+  public function build(ContainerBuilder $container) {
+    // Register the GridManager class with the dependency injection container.
+    $container->register('plugin.manager.grid', 'Drupal\grid\Plugin\GridManager');
+  }
+}
diff --git a/core/modules/grid/lib/Drupal/grid/GridFormController.php b/core/modules/grid/lib/Drupal/grid/GridFormController.php
new file mode 100644
index 0000000..e8b4f9c
--- /dev/null
+++ b/core/modules/grid/lib/Drupal/grid/GridFormController.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\grid\GridFormController.
+ */
+
+namespace Drupal\grid;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityFormController;
+use Drupal\grid\Plugin\Core\Entity\Grid;
+
+/**
+ * Form controller for the grid edit/add forms.
+ */
+class GridFormController extends EntityFormController {
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::prepareEntity().
+   *
+   * Prepares the grid object filling in a few default values.
+   */
+  protected function prepareEntity(EntityInterface $grid) {
+    // If no grid type was specified yet, default to equal_column.
+    if (empty($grid->type)) {
+      $grid->type = 'equal_column';
+      $grid->options = array();
+    }
+    $grid->options = $grid->getPlugin()->prepareOptions($grid->options);
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::form().
+   */
+  public function form(array $form, array &$form_state, EntityInterface $grid) {
+    $form['label'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Label'),
+      '#maxlength' => 255,
+      '#default_value' => $grid->label(),
+      '#required' => TRUE,
+    );
+    $form['id'] = array(
+      '#type' => 'machine_name',
+      '#default_value' => $grid->id(),
+      '#machine_name' => array(
+        'exists' => 'grid_load',
+        'source' => array('label'),
+      ),
+      '#disabled' => !$grid->isNew(),
+    );
+    $form['type'] = array(
+      '#type' => 'value',
+      '#value' => $grid->type,
+    );
+    $form['grid'] = array(
+      '#type' => 'value',
+      '#value' => $grid,
+    );
+    $form['options'] = $grid->getPlugin()->form($form, $form_state, $grid->options);
+
+    return parent::form($form, $form_state, $grid);
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::validate().
+   */
+  public function validate(array $form, array &$form_state) {
+    $form_state['values']['grid']->getPlugin()->validate($form, $form_state['values']['options']);
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::actions().
+   */
+  protected function actions(array $form, array &$form_state) {
+    // Only includes a Save action for the entity, no direct Delete button.
+    return array(
+      'submit' => array(
+        '#value' => t('Save'),
+        '#validate' => array(
+          array($this, 'validate'),
+        ),
+        '#submit' => array(
+          array($this, 'submit'),
+          array($this, 'save'),
+        ),
+      ),
+    );
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::save().
+   */
+  public function save(array $form, array &$form_state) {
+    $grid = $this->getEntity($form_state);
+    $grid->save();
+
+    watchdog('grid', 'Grid @label saved.', array('@label' => $grid->label()), WATCHDOG_NOTICE);
+    drupal_set_message(t('Grid %label saved.', array('%label' => $grid->label())));
+
+    $form_state['redirect'] = 'admin/structure/grids';
+  }
+
+}
diff --git a/core/modules/grid/lib/Drupal/grid/Plugin/Core/Entity/Grid.php b/core/modules/grid/lib/Drupal/grid/Plugin/Core/Entity/Grid.php
new file mode 100644
index 0000000..78b1774
--- /dev/null
+++ b/core/modules/grid/lib/Drupal/grid/Plugin/Core/Entity/Grid.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\grid\Plugin\Core\Entity\Grid.
+ */
+
+namespace Drupal\grid\Plugin\Core\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\grid\Plugin\GridInterface;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Defines the grid entity class.
+ *
+ * @Plugin(
+ *   id = "grid",
+ *   label = @Translation("Grid"),
+ *   module = "grid",
+ *   controller_class =  "Drupal\Core\Config\Entity\ConfigStorageController",
+ *   form_controller_class = {
+ *     "default" = "Drupal\grid\GridFormController",
+ *   },
+ *   list_controller_class = "Drupal\Core\Config\Entity\ConfigEntityListController",
+ *   list_path = "admin/structure/grids",
+ *   uri_callback = "grid_uri",
+ *   config_prefix = "grid",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "label" = "label",
+ *     "uuid" = "uuid",
+ *   }
+ * ) */
+class Grid extends ConfigEntityBase implements GridInterface {
+
+  /**
+   * The grid ID (machine name).
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The grid UUID.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * The grid label.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * Plugin identifier for this grid.
+   *
+   * @var string
+   */
+  public $type;
+
+  /**
+   * Plugin configuration to instantiate the plugin instance.
+   *
+   * @var array
+   */
+  public $options;
+
+  /**
+   * Instantiated plugin to handle the grid.
+   *
+   * @see Drupal\grid\Grid::GetPlugin().
+   *
+   * @var Drupal\grid\Plugin\GridInterface
+   */
+  protected $plugin;
+
+  /**
+   * Get a plugin instance for this grid.
+   */
+  public function getPlugin() {
+    if (!isset($this->plugin)) {
+      // Pass on Grid ID as part of the configuration array.
+      $this->options['id'] = $this->id;
+      $this->plugin = drupal_container()->get('plugin.manager.grid')->createInstance($this->type, $this->options);
+    }
+    return $this->plugin;
+  }
+
+  /**
+   * Implements Drupal\grid\Plugin\GridInterface::getGridCss().
+   */
+  public function getGridCss($wrapper_selector = NULL, $col_selector_prefix = NULL, $skip_spacing = FALSE) {
+    return $this->getPlugin()->getGridCss($wrapper_selector, $col_selector_prefix, $skip_spacing);
+  }
+
+}
diff --git a/core/modules/grid/lib/Drupal/grid/Plugin/GridInterface.php b/core/modules/grid/lib/Drupal/grid/Plugin/GridInterface.php
new file mode 100644
index 0000000..ca73fd8
--- /dev/null
+++ b/core/modules/grid/lib/Drupal/grid/Plugin/GridInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\grid\Plugin\GridInterface.
+ */
+
+namespace Drupal\grid\Plugin;
+
+/**
+ * Defines the shared interface for all grid plugins.
+ */
+interface GridInterface {
+
+  /**
+   * Generates grid CSS for this grid system.
+   *
+   * @param (string) $wrapper_selector
+   *   (optional) Wrapper CSS selector to use to scope the CSS.
+   * @param (string) $col_selector_prefix
+   *   (optional) Column selector prefix to scope the CSS.
+   * @param (boolean) $skip_spacing
+   *    Whether we should skip including spacing in the output. Useful for tight
+   *    layout demonstration presentation.
+   *
+   * @return string
+   *   Grid CSS for this grid system.
+   */
+  public function getGridCss($wrapper_selector = NULL, $col_selector_prefix = NULL, $skip_spacing = FALSE);
+}
diff --git a/core/modules/grid/lib/Drupal/grid/Plugin/GridManager.php b/core/modules/grid/lib/Drupal/grid/Plugin/GridManager.php
new file mode 100644
index 0000000..78516f1
--- /dev/null
+++ b/core/modules/grid/lib/Drupal/grid/Plugin/GridManager.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\grid\Plugin\GridManager.
+ */
+
+namespace Drupal\grid\Plugin;
+
+use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\Component\Plugin\Factory\ReflectionFactory;
+
+/**
+ * Grid plugin manager.
+ */
+class GridManager extends PluginManagerBase {
+
+  /**
+   * Overrides Drupal\Component\Plugin\PluginManagerBase::__construct().
+   */
+  public function __construct() {
+    $this->discovery = new AnnotatedClassDiscovery('grid', 'grid');
+    $this->factory = new ReflectionFactory($this);
+  }
+}
diff --git a/core/modules/grid/lib/Drupal/grid/Plugin/grid/grid/EqualColumn.php b/core/modules/grid/lib/Drupal/grid/Plugin/grid/grid/EqualColumn.php
new file mode 100644
index 0000000..94b631e
--- /dev/null
+++ b/core/modules/grid/lib/Drupal/grid/Plugin/grid/grid/EqualColumn.php
@@ -0,0 +1,250 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\grid\Plugin\grid\grid\EqualColumn.
+ */
+
+namespace Drupal\grid\Plugin\grid\grid;
+
+use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+use Drupal\grid\Plugin\GridInterface;
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\Core\Annotation\Plugin;
+
+/**
+ * @Plugin(
+ *  id = "equal_column"
+ * )
+ */
+class EqualColumn implements GridInterface {
+
+  /**
+   * The grid ID (machine name).
+   *
+   * @var string
+   */
+  protected $id;
+
+  /**
+   * The total numeric width of the grid without units.
+   *
+   * For example, '960' for a 960px grid or '100' for a fluid (100%) grid.
+   *
+   * @var string
+   */
+  protected $width;
+
+  /**
+   * The size units that width, gutter, and padding are in.
+   *
+   * For example, 'px', 'em', or '%'.
+   *
+   * @var string
+   */
+  protected $units;
+
+  /**
+   * The number of columns.
+   *
+   * @var string
+   */
+  protected $columns;
+
+  /**
+   * The gutter width.
+   *
+   * @var string
+   */
+  protected $gutter;
+
+  /**
+   * The padding width.
+   *
+   * @var string
+   */
+  protected $padding;
+
+  /**
+   * Constructor.
+   */
+  public function __construct($id, $units, $width, $columns, $padding_width, $gutter_width) {
+    $this->id = $id;
+    $this->columns = $columns;
+    $this->padding = $padding_width;
+    $this->gutter = $gutter_width;
+    $this->width = $width;
+    $this->units = $units;
+  }
+
+  /**
+   * Prepare grid entity.
+   */
+  public function prepareOptions(array $options) {
+    if (empty($options['width'])) {
+      // Set some defaults for the user if this is a new grid.
+      $options['units'] = '%';
+      $options['width'] = 100;
+      $options['columns'] = 12;
+      $options['padding_width'] = 1.5;
+      $options['gutter_width'] = 2;
+    }
+    return $options;
+  }
+
+  /**
+   * Form elements for grid editing.
+   */
+  public function form(array $full_form, array &$form_state, array $options) {
+    // Master grid configuration.
+    $form['units'] = array(
+      '#type' => 'radios',
+      '#title' => t('Grid units'),
+      '#options' => array('%' => t('Percentages'), 'em' => t('Em-based'), 'px' => t('Pixel based')),
+      '#default_value' => $options['units'],
+    );
+    $form['width'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Grid width'),
+      '#description' => t('Width of the grid in unit set above. For example 960 (pixels) or 100 (percent).'),
+      '#default_value' => $options['width'],
+    );
+
+    // Grid detail configuration.
+    $form['columns'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Number of grid columns'),
+      '#default_value' => $options['columns'],
+    );
+    $form['padding_width'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Column padding'),
+      '#description' => t('Column padding in unit set above. For example 10 (pixels) or 1.5 (percent). Enter 0 for no padding.'),
+      '#default_value' => $options['padding_width'],
+    );
+
+    $form['gutter_width'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Gutter width'),
+      '#description' => t('Gutter width in unit set above. For example 20 (pixels) or 1.5 (percent). Enter 0 for no padding.'),
+      '#default_value' => $options['gutter_width'],
+    );
+    return $form;
+  }
+
+  /**
+   * Form validation callback.
+   */
+  public function validate(array $form, array &$options_state) {
+    if ((intval($options_state['width']) != $options_state['width']) || $options_state['width'] == 0) {
+      // Width should be a positive integer.
+      form_set_error('columns', t('The width should be a positive number.'));
+    }
+    if ((intval($options_state['columns']) != $options_state['columns']) || $options_state['columns'] == 0) {
+      // Columns should be a positive integer.
+      form_set_error('columns', t('The number of columns should be a positive number.'));
+    }
+    if (!is_numeric($options_state['padding_width'])) {
+      // Padding can be float as well (eg. 1.5 for 1.5% for fluid grids).
+      form_set_error('padding_width', t('The column padding should be a number. Enter 0 (zero) for no padding.' . $options_state['padding_width']));
+    }
+    if (!is_numeric($options_state['gutter_width'])) {
+      // Gutter can be float too (eg. 1.5 for 1.5% for fluid grids).
+      form_set_error('gutter_width', t('The gutter width should be a number. Enter 0 (zero) for no gutter.'));
+    }
+  }
+
+  /**
+   * Implements Drupal\grid\Plugin\GridInterface::getGridCss().
+   */
+  public function getGridCss($wrapper_selector = NULL, $col_selector_prefix = NULL, $skip_spacing = FALSE) {
+
+    // If the wrapper selector was not provided, generate one. This is useful for
+    // specific administration use cases when we scope the classes by grids.
+    if (empty($wrapper_selector)) {
+      $wrapper_selector = '.grid-' . $this->id;
+    }
+
+    // If the col span selector was not provided, generate one. This is useful
+    // for the front end to apply varying span widths under different names.
+    if (empty($col_selector_prefix)) {
+      $col_selector_prefix = '.grid-col-';
+    }
+
+    // If spacing is to be skipped, use 0 instead of the configured values.
+    if ($skip_spacing) {
+      $padding = 0;
+      $gutter = 0;
+    }
+    else {
+      $padding = $this->padding;
+      $gutter = $this->gutter;
+    }
+
+    // Because we use the border-box box model, we only need to substract the
+    // size of margins from the full width and divide the rest by number of
+    // columns to get a value for column size.
+    $colwidth = ($this->width - (($this->columns - 1) * $gutter)) / $this->columns;
+
+    $css = array();
+    $css[$wrapper_selector . ' .grid-col'] = array(
+      'border' => '0px solid rgba(0,0,0,0)',
+      'float' => 'left',
+      '-webkit-box-sizing' => 'border-box',
+      '-moz-box-sizing' => 'border-box',
+      'box-sizing' => 'border-box',
+      '-moz-background-clip' => 'padding-box',
+      '-webkit-background-clip' => 'padding-box',
+      'background-clip' => 'padding-box',
+      'margin-left' => $gutter . $this->units,
+      'padding' => '0 ' . $padding  . $this->units,
+    );
+    $css[$wrapper_selector . ' .grid-col' . $col_selector_prefix . 'first'] = array(
+      'margin-left' => '0',
+      'clear' => 'both',
+    );
+    for ($i = 1; $i <= $this->columns; $i++) {
+      $selector = $wrapper_selector . ' .grid-col' . $col_selector_prefix . $i;
+      if ($i == 1) {
+        // The first column does not yet have any margins.
+        $css[$selector] = array(
+          'width' => ($colwidth * $i) . $this->units,
+        );
+      }
+      elseif ($i == $this->columns) {
+        // The last column always spans 100%.
+        $css[$selector] = array(
+          'width' => $this->width . $this->units,
+          'margin-left' => 0,
+        );
+      }
+      else {
+        // Other columns absorb all columns that they need to include and one
+        // less margin before them.
+        $css[$selector] = array(
+          'width' => (($colwidth * $i) + ($gutter * ($i - 1))) . $this->units,
+        );
+      }
+    }
+
+    return $this->formatCss($css);
+  }
+
+  /**
+   * Returns a CSS string.
+   *
+   * @param (array) $css
+   *   A two dimensional array, keyed first on selector, then on property name.
+   */
+  protected function formatCss($css) {
+    $output = '';
+    foreach ($css as $selector => $rules) {
+      $output .= $selector . "{\n";
+      foreach ($rules as $property => $value) {
+        $output .= '  ' . $property . ': ' . $value . ";\n";
+      }
+      $output .= "}\n";
+    }
+    return $output;
+  }
+}
