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 3956202..b74f830 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
@@ -94,7 +94,9 @@ protected function defineOptions() {
     $options['override'] = array('default' => TRUE, 'bool' => TRUE);
     $options['sticky'] = array('default' => FALSE, 'bool' => TRUE);
     $options['order'] = array('default' => 'asc');
+    $options['caption'] = array('default' => '', 'translatable' => TRUE);
     $options['summary'] = array('default' => '', 'translatable' => TRUE);
+    $options['description'] = array('default' => '', 'translatable' => TRUE);
     $options['empty_table'] = array('default' => FALSE, 'bool' => TRUE);
 
     return $options;
@@ -242,12 +244,38 @@ public function buildOptionsForm(&$form, &$form_state) {
       '#description' => t('(Sticky header effects will not be active for preview below, only on live output.)'),
     );
 
+    $form['caption'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Caption for the table'),
+      '#description' => t('A title which is semantically associated to your table for increased accessibility.'),
+      '#default_value' => $this->options['caption'],
+      '#maxlength' => 255,
+    );
+
+    $form['accessibility_details'] = array(
+      '#type' => 'details',
+      '#title' => t('Table details'),
+      '#collapsed' => TRUE,
+    );
+
     $form['summary'] = array(
+      '#title' => t('Summary title'),
       '#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.'),
       '#default_value' => $this->options['summary'],
-      '#maxlength' => 255,
+      '#fieldset' => 'accessibility_details',
+    );
+
+    $form['description'] = array(
+      '#title' => t('Table description'),
+      '#type' => 'textarea',
+      '#description' => t('Provide additional details about the table to increase accessibility.'),
+      '#default_value' => $this->options['description'],
+      '#states' => array(
+        'visible' => array(
+          'input[name="style_options[summary]"]' => array('filled' => TRUE),
+        ),
+      ),
+      '#fieldset' => 'accessibility_details',
     );
 
     // Note: views UI registers this theme handler on our behalf. Your module
diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleTableTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleTableTest.php
new file mode 100644
index 0000000..5bcca66
--- /dev/null
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/StyleTableTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Tests\Plugin\StyleTableTest.
+ */
+
+namespace Drupal\views\Tests\Plugin;
+
+class StyleTableTest extends PluginTestBase {
+
+  /**
+   * Views used by this test.
+   *
+   * @var array
+   */
+  public static $testViews = array('test_table');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Style: Table',
+      'description' => 'Tests the table style plugin.',
+      'group' => 'Views Plugins',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->enableViewsTestModule();
+  }
+
+  /**
+   * Test table caption/summary/description.
+   */
+  public function testAccessibilitySettings() {
+    $this->drupalGet('test-table');
+
+    $result = $this->xpath('//caption');
+    $this->assertTrue(count($result), 'The caption appears on the table.');
+    $this->assertEqual(trim((string) $result[0]), 'caption-text');
+
+    $result = $this->xpath('//summary');
+    $this->assertTrue(count($result), 'The summary appears on the table.');
+    $this->assertEqual(trim((string) $result[0]), 'summary-text');
+
+    $result = $this->xpath('//caption/details');
+    $this->assertTrue(count($result), 'The table description appears on the table.');
+    $this->assertEqual(trim((string) $result[0]), 'description-text');
+
+    // Remove the caption and ensure the caption is not displayed anymore.
+    $view = entity_load('view', 'test_table');
+    $display = &$view->getDisplay('default');
+    $display['display_options']['style']['options']['caption'] = '';
+    $view->save();
+
+    $this->drupalGet('test-table');
+    $result = $this->xpath('//caption');
+    $this->assertFalse(trim((string) $result[0]), 'Ensure that the caption disappears.');
+
+    // Remove the table summary.
+    $display = &$view->getDisplay('default');
+    $display['display_options']['style']['options']['summary'] = '';
+    $view->save();
+
+    $this->drupalGet('test-table');
+    $result = $this->xpath('//summary');
+    $this->assertFalse(count($result), 'Ensure that the summary disappears.');
+
+    // Remove the table description.
+    $display = &$view->getDisplay('default');
+    $display['display_options']['style']['options']['description'] = '';
+    $view->save();
+
+    $this->drupalGet('test-table');
+    $result = $this->xpath('//caption/details');
+    $this->assertFalse(count($result), 'Ensure that the description disappears.');
+  }
+
+}
diff --git a/core/modules/views/templates/views-view-table.html.twig b/core/modules/views/templates/views-view-table.html.twig
index 50ae9d6..f3bc6e4 100644
--- a/core/modules/views/templates/views-view-table.html.twig
+++ b/core/modules/views/templates/views-view-table.html.twig
@@ -10,6 +10,10 @@
  * - header: Header labels.
  * - header_classes: HTML classes to apply to each header cell, indexed by
  *   the header's key.
+ * - caption_needed: Is the caption tag needed.
+ * - caption: The caption for this table.
+ * - accessibility_description: Extended description for the table details.
+ * - accessibility_summary: Summary for the table details.
  * - rows: Table row items. Rows are keyed by row number, fields within rows
  *   are keyed by field ID.
  *   - field: Table data field ID.
@@ -26,8 +30,24 @@
  */
 #}
 <table{{ attributes }}>
-  {% if title is not empty %}
-    <caption>{{ title }}</caption>
+  {% if caption_needed %}
+    <caption>
+    {% if caption %}
+      {{ caption }}
+    {% else %}
+      {{ title }}
+    {% endif %}
+    {% if (summary is not empty) or (description is not empty) %}
+      <details>
+        {% if summary is not empty %}
+          <summary>{{ summary }}</summary>
+        {% endif %}
+        {% if description is not empty %}
+          {{ description }}
+        {% endif %}
+      </details>
+    {% endif %}
+    </caption>
   {% endif %}
   {% if header %}
     <thead>
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_table.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_table.yml
index 49ae0e9..991fbdf 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_table.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_table.yml
@@ -80,6 +80,9 @@ display:
               responsive: ''
           default: 'id'
           empty_table: '1'
+          caption: caption-text
+          summary: summary-text
+          description: description-text
       row:
         type: fields
       empty:
@@ -99,6 +102,13 @@ display:
     display_title: Master
     id: default
     position: '0'
+  page_1:
+    display_options:
+      path: 'test-table'
+    display_plugin: page
+    display_title: 'Page display'
+    id: page_1
+    position: '1'
 label: ''
 id: test_table
 tag: ''
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index 42dd2f6..9980f6c 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -5,6 +5,7 @@
  * Preprocessors and helper functions to make theming easier.
  */
 
+use Drupal\Component\Utility\Xss;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Template\Attribute;
 use Drupal\views\ViewExecutable;
@@ -736,13 +737,24 @@ function template_preprocess_views_view_table(&$vars) {
   }
   $vars['attributes']['class'][] = 'cols-' . count($vars['header']);
 
-  if (!empty($handler->options['summary'])) {
-    $vars['attributes']['summary'] = $handler->options['summary'];
+  // Add the caption to the list if set.
+  if (!empty($handler->options['caption'])) {
+    $vars['caption'] = Xss::filterAdmin($handler->options['caption']);
+    $vars['caption_needed'] = TRUE;
+  }
+  else {
+    $vars['caption'] = '';
+    $vars['caption_needed'] = FALSE;
   }
+
+  $vars['summary'] = $handler->options['summary'];
+  $vars['description'] = $handler->options['description'];
+  $vars['caption_needed'] |= !empty($vars['summary']) || !empty($vars['description']);
+
   // 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']) && $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.
