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..e170dd7
--- /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:
+  type: 'fluid'
+  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..258133c
--- /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:
+  type: 'fluid'
+  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..319aacc
--- /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:
+  type: 'fluid'
+  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..405317c
--- /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:
+  type: 'fixed'
+  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..4ddff62
--- /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:
+  type: 'fixed'
+  width: 960
+  columns: 16
+  padding_width: 20
+  gutter_width: 10
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..396ae6e
--- /dev/null
+++ b/core/modules/grid/grid.module
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Pluggable grid system manager module.
+ */
+
+use Drupal\grid\Grid;
+
+/**
+ * Implements hook_entity_info().
+ */
+function grid_entity_info() {
+  $types['grid'] = array(
+    'label' => 'Grid',
+    'entity class' => 'Drupal\grid\Grid',
+    'controller class' => 'Drupal\Core\Config\Entity\ConfigStorageController',
+    'config prefix' => 'grid',
+    'entity keys' => array(
+      'id' => 'id',
+      'label' => 'label',
+      'uuid' => 'uuid',
+    ),
+  );
+  return $types;
+}
diff --git a/core/modules/grid/lib/Drupal/grid/Grid.php b/core/modules/grid/lib/Drupal/grid/Grid.php
new file mode 100644
index 0000000..af122e5
--- /dev/null
+++ b/core/modules/grid/lib/Drupal/grid/Grid.php
@@ -0,0 +1,81 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\grid\Grid.
+ */
+
+namespace Drupal\grid;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\grid\Plugin\GridInterface;
+
+/**
+ * Defines the grid entity.
+ */
+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/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/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..fefd24f
--- /dev/null
+++ b/core/modules/grid/lib/Drupal/grid/Plugin/grid/grid/EqualColumn.php
@@ -0,0 +1,179 @@
+<?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, $type, $width, $columns, $padding_width, $gutter_width) {
+    $this->id = $id;
+    $this->columns = $columns;
+    $this->padding = $padding_width;
+    $this->gutter = $gutter_width;
+    if ($type === 'fluid') {
+      $this->width = 100;
+      $this->units = '%';
+    }
+    else {
+      $this->width = $width;
+      $this->units = 'px';
+    }
+  }
+
+  /**
+   * 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;
+  }
+}
