diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/style/Grid.php b/core/modules/views/lib/Drupal/views/Plugin/views/style/Grid.php
index 0cfaa2d..8634041 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/style/Grid.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/style/Grid.php
@@ -49,6 +49,7 @@ protected function defineOptions() {
     $options['alignment'] = array('default' => 'horizontal');
     $options['fill_single_line'] = array('default' => TRUE, 'bool' => TRUE);
     $options['summary'] = array('default' => '');
+    $options['caption'] = array('default' => '');
 
     return $options;
   }
@@ -82,10 +83,17 @@ public function buildOptionsForm(&$form, &$form_state) {
 
     $form['summary'] = array(
       '#type' => 'textfield',
-      '#title' => t('Table summary'),
-      '#description' => t('This value will be displayed as table-summary attribute in the html. Set this for better accessiblity of your site.'),
+      '#title' => t('Summary of table organization'),
+      '#description' => t('The table attribute should be used to increase accessibility by providing a summary of complex tables to describe how they are laid out structurally.'),
       '#default_value' => $this->options['summary'],
     );
-  }
 
-}
+    $form['caption'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Title of the table'),
+      '#description' => t('A title which is semantically associated to your table for increased accessibility.'),
+      '#default_value' => $this->options['caption'],
+      '#maxlength' => 255,
+    );
+  }
+}
\ No newline at end of file
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/style/Table.php b/core/modules/views/lib/Drupal/views/Plugin/views/style/Table.php
index 5a3e907..a7ddbc8 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/style/Table.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/style/Table.php
@@ -69,6 +69,7 @@ protected function defineOptions() {
     $options['sticky'] = array('default' => FALSE, 'bool' => TRUE);
     $options['order'] = array('default' => 'asc');
     $options['summary'] = array('default' => '', 'translatable' => TRUE);
+    $options['caption'] = array('default' => '', 'translatable' => TRUE);
     $options['empty_table'] = array('default' => FALSE, 'bool' => TRUE);
 
     return $options;
@@ -220,12 +221,20 @@ public function buildOptionsForm(&$form, &$form_state) {
 
     $form['summary'] = array(
       '#type' => 'textfield',
-      '#title' => t('Table summary'),
-      '#description' => t('This value will be displayed as table-summary attribute in the html. Set this for better accessiblity of your site.'),
+      '#title' => t('Summary of table organization'),
+      '#description' => t('The table attribute should be used to increase accessibility by providing a summary of complex tables to describe how they are laid out structurally.'),
       '#default_value' => $this->options['summary'],
       '#maxlength' => 255,
     );
 
+    $form['caption'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Title of the table'),
+      '#description' => t('A title which is semantically associated to your table for increased accessibility.'),
+      '#default_value' => $this->options['caption'],
+      '#maxlength' => 255,
+    );
+
     // Note: views UI registers this theme handler on our behalf. Your module
     // will have to register your theme handlers if you do stuff like this.
     $form['#theme'] = 'views_ui_style_plugin_table';
diff --git a/core/modules/views/templates/views-view-grid.tpl.php b/core/modules/views/templates/views-view-grid.tpl.php
index 43ba37b..59907d6 100644
--- a/core/modules/views/templates/views-view-grid.tpl.php
+++ b/core/modules/views/templates/views-view-grid.tpl.php
@@ -14,9 +14,12 @@
   <h3><?php print $title; ?></h3>
 <?php endif; ?>
 <table <?php print $attributes; ?>>
+  <?php if (isset($caption) && !empty($caption)) : ?>
+    <caption><?php print $caption; ?></caption>
+  <?php endif; ?>
   <tbody>
     <?php foreach ($rows as $row_number => $columns): ?>
-      <tr <?php print $row_classes[$row_number]; ?>>
+      <tr <?php print (isset($row_classes[$row_number])) ? $row_classes[$row_number] : ''; ?>>
         <?php foreach ($columns as $column_number => $item): ?>
           <td <?php print $column_classes[$row_number][$column_number]; ?>>
             <?php print $item; ?>
diff --git a/core/modules/views/templates/views-view-table.tpl.php b/core/modules/views/templates/views-view-table.tpl.php
index 4d44d42..88b501b 100644
--- a/core/modules/views/templates/views-view-table.tpl.php
+++ b/core/modules/views/templates/views-view-table.tpl.php
@@ -7,6 +7,7 @@
  * - $title : The title of this group of rows.  May be empty.
  * - $header: An array of header labels keyed by field id.
  * - $header_classes: An array of header classes keyed by field id.
+ * - $caption: The caption for this table. May be empty.
  * - $fields: An array of CSS IDs to use for each field id.
  * - $classes: A class or classes to apply to the table, based on settings.
  * - $row_classes: An array of classes to apply to each row, indexed by row
@@ -20,8 +21,8 @@
 
 ?>
 <table <?php print $attributes; ?>>
-  <?php if (!empty($title)) : ?>
-    <caption><?php print $title; ?></caption>
+   <?php if (!empty($title) || (isset($caption) && !empty($caption))) : ?>
+     <caption><?php print (!empty($caption)) ? $caption : $title; ?></caption>
   <?php endif; ?>
   <?php if (!empty($header)) : ?>
     <thead>
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index 395f275..80dc9bb 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -653,6 +653,10 @@ function template_preprocess_views_view_table(&$vars) {
   if (!empty($handler->options['summary'])) {
     $vars['attributes_array'] = array('summary' => $handler->options['summary']);
   }
+
+  // Add the caption to the list if set.
+  $vars['caption'] = (!empty($handler->options['caption'])) ? filter_xss_admin($handler->options['caption']) : '';
+
   // If the table has headers and it should react responsively to columns hidden
   // with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM
   // and RESPONSIVE_PRIORITY_LOW, add the tableresponsive behaviors.
@@ -773,13 +777,19 @@ function template_preprocess_views_view_grid(&$vars) {
     }
   }
   $vars['rows'] = $rows;
+
+  // Add the summary to the list if set.
   if (!empty($handler->options['summary'])) {
-    $vars['attributes_array'] = array('summary' => $handler->options['summary']);
+    $vars['attributes_array'] = array('summary' => filter_xss_admin($handler->options['summary']));
   }
+
+  // Add the caption to the list if set.
+  $vars['caption'] = (!empty($handler->options['caption'])) ? filter_xss_admin($handler->options['caption']) : '';
+
   // If the table has headers and it should react responsively to columns hidden
   // with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM
   // and RESPONSIVE_PRIORITY_LOW, add the tableresponsive behaviors.
-  if (count($vars['header']) && $responsive) {
+  if (isset($vars['header']) && count($vars['header']) && $responsive) {
     $vars['view']->element['#attached']['library'][] = array('system', 'drupal.tableresponsive');
     // Add 'responsive-enabled' class to the table to identify it for JS.
     // This is needed to target tables constructed by this function.
