From d26e8a7d574844d7a21e2a888a3bd35dc0bf5959 Mon Sep 17 00:00:00 2001
From: webchick <webchick@24967.no-reply.drupal.org>
Date: Mon, 26 Nov 2012 23:06:47 -0800
Subject: [PATCH] Issue #1168246 by sun, mgifford, Manuel Garcia, mbrett5062,
 ry5n, Everett Zufelt, nod_, aspilicious, deviantintegral, tim.plunkett:
 Freedom For Fieldsets! Long Live The DETAILS.

---
 core/includes/authorize.inc                   |   8 +-
 core/includes/common.inc                      |   4 +-
 core/includes/form.inc                        |  91 ++++++---
 core/includes/install.core.inc                |   8 +-
 core/includes/theme.inc                       |   3 +
 .../Drupal/Core/Database/Install/Tasks.php    |   2 +-
 .../Drupal/Core/FileTransfer/FileTransfer.php |   2 +-
 core/misc/collapse.js                         | 101 ++++++----
 core/misc/states.js                           |   8 +-
 core/misc/vertical-tabs.css                   |   9 +-
 core/misc/vertical-tabs.js                    |  49 ++---
 core/modules/action/action.admin.inc          |   2 +-
 core/modules/aggregator/aggregator.admin.inc  |   2 +-
 .../aggregator/aggregator.processor.inc       |   4 +-
 core/modules/block/block.admin.inc            |  10 +-
 core/modules/block/block.module               |   4 +-
 core/modules/book/book.js                     |   4 +-
 core/modules/book/book.module                 |   4 +-
 core/modules/color/color.module               |   2 +-
 core/modules/comment/comment-node-form.js     |   6 +-
 core/modules/comment/comment.admin.inc        |   2 +-
 core/modules/comment/comment.module           |   4 +-
 .../Drupal/comment/CommentFormController.php  |   4 +-
 core/modules/contact/contact.module           |   4 +-
 core/modules/dblog/dblog.admin.inc            |   4 +-
 .../Drupal/field/Plugin/views/field/Field.php |   2 +-
 .../modules/field_test/field_test.entity.inc  |   2 +-
 core/modules/field_ui/field_ui.admin.inc      |  18 +-
 .../lib/Drupal/field_ui/DisplayOverview.php   |   2 +-
 .../file/Plugin/field/widget/FileWidget.php   |   2 +-
 core/modules/filter/filter.admin-rtl.css      |   4 -
 core/modules/filter/filter.admin.css          |  13 +-
 core/modules/filter/filter.admin.inc          |   2 +-
 core/modules/filter/filter.admin.js           |   2 +-
 core/modules/filter/filter.module             |   8 +-
 .../lib/Drupal/forum/Tests/ForumTest.php      |   6 +-
 core/modules/language/language.admin.inc      |   6 +-
 .../Drupal/locale/Tests/LocaleContentTest.php |   2 +-
 core/modules/locale/locale.admin.css          |   9 +-
 core/modules/locale/locale.bulk.inc           |   2 +-
 core/modules/locale/locale.pages.inc          |   2 +-
 core/modules/menu/menu.admin.js               |   4 +-
 core/modules/menu/menu.js                     |   8 +-
 core/modules/menu/menu.module                 |   4 +-
 core/modules/node/content_types.inc           |   8 +-
 core/modules/node/content_types.js            |   8 +-
 .../lib/Drupal/node/NodeFormController.php    |   6 +-
 core/modules/node/node.admin.inc              |   4 +-
 core/modules/node/node.js                     |   8 +-
 core/modules/node/node.module                 |   6 +-
 core/modules/overlay/overlay.module           |   2 +-
 core/modules/path/path.admin.inc              |   2 +-
 core/modules/path/path.js                     |   4 +-
 core/modules/path/path.module                 |   2 +-
 core/modules/poll/poll.module                 |   2 +-
 core/modules/search/search.admin.inc          |   8 +-
 core/modules/search/search.api.php            |   2 +-
 .../simpletest/Tests/SimpleTestTest.php       |  18 +-
 .../lib/Drupal/simpletest/WebTestBase.php     |   2 +-
 core/modules/simpletest/simpletest.pages.inc  |  18 +-
 core/modules/statistics/statistics.admin.inc  |   4 +-
 .../system/Tests/Common/ArrayUnitTest.php     |  14 +-
 .../Drupal/system/Tests/Common/RenderTest.php |  14 +-
 core/modules/system/system.admin.inc          |  44 ++---
 core/modules/system/system.base.css           |  22 +--
 core/modules/system/system.module             |  19 +-
 core/modules/system/system.theme-rtl.css      |  19 +-
 core/modules/system/system.theme.css          |  48 +++--
 .../modules/design_test/design_test.info      |   6 +
 .../modules/design_test/design_test.module    | 169 +++++++++++++++++
 .../modules/design_test/form/details.inc      | 178 ++++++++++++++++++
 .../modules/design_test/form/fieldset.inc     | 101 ++++++++++
 .../design_test/page/list-operations.inc      |  84 +++++++++
 .../tests/modules/form_test/form_test.module  |   4 +-
 .../modules/theme_test/theme_test.module      |  90 ---------
 .../Drupal/taxonomy/TermFormController.php    |   2 +-
 .../taxonomy/VocabularyFormController.php     |   2 +-
 core/modules/translation/translation.module   |   2 +-
 .../EntityTranslationController.php           |   6 +-
 .../lib/Drupal/user/AccountFormController.php |   4 +-
 .../Drupal/user/Tests/UserLanguageTest.php    |   2 +-
 .../user/Tests/UserRegistrationTest.php       |   6 +-
 core/modules/user/user.admin.inc              |  30 +--
 core/modules/user/user.css                    |   2 +-
 .../Drupal/views/Plugin/views/HandlerBase.php |   4 +-
 .../Plugin/views/area/AreaPluginBase.php      |   2 +-
 .../views/argument/ArgumentPluginBase.php     |   8 +-
 .../Plugin/views/field/FieldPluginBase.php    |   8 +-
 .../Drupal/views/Plugin/views/pager/Full.php  |   4 +-
 .../views/Plugin/views/row/RssFields.php      |   2 +-
 .../Plugin/views/wizard/WizardPluginBase.php  |   8 +-
 core/modules/views/views_ui/admin.inc         |  10 +-
 .../views/views_ui/css/views-admin-rtl.css    |   9 +-
 .../views/views_ui/css/views-admin.css        |  35 +---
 .../views_ui/css/views-admin.theme-rtl.css    |   8 +-
 .../views/views_ui/css/views-admin.theme.css  |  26 ++-
 .../Drupal/views_ui/ViewAddFormController.php |   4 +-
 .../views_ui/ViewEditFormController.php       |   8 +-
 core/themes/bartik/css/style-rtl.css          |   5 +-
 core/themes/bartik/css/style.css              |  89 ++-------
 core/themes/seven/ie.css                      |   6 -
 core/themes/seven/style-rtl.css               |  19 --
 core/themes/seven/style.css                   |  96 +++-------
 core/themes/seven/vertical-tabs-rtl.css       |   3 +-
 core/themes/seven/vertical-tabs.css           |  12 +-
 core/update.php                               |   2 +-
 106 files changed, 1074 insertions(+), 705 deletions(-)
 create mode 100644 core/modules/system/tests/modules/design_test/design_test.info
 create mode 100644 core/modules/system/tests/modules/design_test/design_test.module
 create mode 100644 core/modules/system/tests/modules/design_test/form/details.inc
 create mode 100644 core/modules/system/tests/modules/design_test/form/fieldset.inc
 create mode 100644 core/modules/system/tests/modules/design_test/page/list-operations.inc

diff --git a/core/includes/authorize.inc b/core/includes/authorize.inc
index f98820f9eb97..251ce1104a98 100644
--- a/core/includes/authorize.inc
+++ b/core/includes/authorize.inc
@@ -158,7 +158,7 @@ function _authorize_filetransfer_connection_settings($backend) {
  *
  * The default settings for the file transfer connection forms are saved in
  * the database. The settings are stored as a nested array in the case of a
- * settings form that has fieldsets or otherwise uses a nested structure.
+ * settings form that has details or otherwise uses a nested structure.
  * Therefore, to properly add defaults, we need to walk through all the
  * children form elements and process those defaults recursively.
  *
@@ -170,14 +170,14 @@ function _authorize_filetransfer_connection_settings($backend) {
  *   The default settings for the file transfer backend we're operating on.
  */
 function _authorize_filetransfer_connection_settings_set_defaults(&$element, $key, array $defaults) {
-  // If we're operating on a form element which isn't a fieldset, and we have
+  // If we're operating on a form element which isn't a details, and we have
   // a default setting saved, stash it in #default_value.
-  if (!empty($key) && isset($defaults[$key]) && isset($element['#type']) && $element['#type'] != 'fieldset') {
+  if (!empty($key) && isset($defaults[$key]) && isset($element['#type']) && $element['#type'] != 'details') {
     $element['#default_value'] = $defaults[$key];
   }
   // Now, we walk through all the child elements, and recursively invoke
   // ourself on each one. Since the $defaults settings array can be nested
-  // (because of #tree, any values inside fieldsets will be nested), if
+  // (because of #tree, any values inside details will be nested), if
   // there's a subarray of settings for the form key we're currently
   // processing, pass in that subarray to the recursive call. Otherwise, just
   // pass on the whole $defaults array.
diff --git a/core/includes/common.inc b/core/includes/common.inc
index edd7c2d4ed72..a70b66e8f4a8 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -5375,8 +5375,8 @@ function drupal_render_page($page) {
  *
  * The #theme_wrappers property contains an array of theme functions which will
  * be called, in order, after #theme has run. These can be used to add further
- * markup around the rendered children; e.g., fieldsets add the required markup
- * for a fieldset around their rendered child elements. All wrapper theme
+ * markup around the rendered children; e.g., details add the required markup
+ * for a details element around their rendered child elements. All wrapper theme
  * functions have to include the element's #children property in their output,
  * as it contains the output of the previous theme functions and the rendered
  * children.
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 5634be8f9213..002de6f5c8de 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -256,8 +256,8 @@ function drupal_get_form($form_id) {
  *     handler, and is also used in Ajax handlers.
  *   - has_file_element: Internal. If TRUE, there is a file element and Form API
  *     will set the appropriate 'enctype' HTML attribute on the form.
- *   - groups: Internal. An array containing references to fieldsets to render
- *     them within vertical tabs.
+ *   - groups: Internal. An array containing references to details elements to
+ *     render them within vertical tabs.
  *   - storage: $form_state['storage'] is not a special key, and no specific
  *     support is provided for it in the Form API. By tradition it was
  *     the location where application-specific data was stored for communication
@@ -1706,9 +1706,9 @@ function form_error(&$element, $message = '') {
  *   type, one of the functions in this array is form_process_date(), which adds
  *   the individual 'year', 'month', 'day', etc. child elements. These functions
  *   can also be used to set additional properties or implement special logic
- *   other than adding child elements: for example, for the 'fieldset' element
- *   type, one of the functions in this array is form_process_fieldset(), which
- *   adds the attributes and JavaScript needed to make the fieldset collapsible
+ *   other than adding child elements: for example, for the 'details' element
+ *   type, one of the functions in this array is form_process_details(), which
+ *   adds the attributes and JavaScript needed to make the details collapsible
  *   if the #collapsible property is set. The #process functions are called in
  *   preorder traversal, meaning they are called for the parent element first,
  *   then for the child elements.
@@ -2813,6 +2813,39 @@ function theme_fieldset($variables) {
   return $output;
 }
 
+/**
+ * Returns HTML for a details form element and its children.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - element: An associative array containing the properties of the element.
+ *     Properties used: #attributes, #children, #collapsed, #collapsible,
+ *     #description, #id, #title, #value.
+ *
+ * @ingroup themeable
+ */
+function theme_details($variables) {
+  $element = $variables['element'];
+  element_set_attributes($element, array('id'));
+  _form_set_attributes($element, array('form-wrapper'));
+
+  $output = '<details' . new Attribute($element['#attributes']) . '>';
+  if (!empty($element['#title'])) {
+    $output .= '<summary>' . $element['#title'] . '</summary>';
+  }
+  $output .= '<div class="details-wrapper">';
+  if (!empty($element['#description'])) {
+    $output .= '<div class="details-description">' . $element['#description'] . '</div>';
+  }
+  $output .= $element['#children'];
+  if (isset($element['#value'])) {
+    $output .= $element['#value'];
+  }
+  $output .= '</div>';
+  $output .= "</details>\n";
+  return $output;
+}
+
 /**
  * Returns HTML for a radio button form element.
  *
@@ -3670,29 +3703,29 @@ function form_validate_machine_name(&$element, &$form_state) {
 }
 
 /**
- * Arranges fieldsets into groups.
+ * Arranges details into groups.
  *
  * @param $element
  *   An associative array containing the properties and children of the
- *   fieldset. Note that $element must be taken by reference here, so processed
+ *   details. Note that $element must be taken by reference here, so processed
  *   child elements are taken over into $form_state.
  * @param $form_state
- *   The $form_state array for the form this fieldset belongs to.
+ *   The $form_state array for the form this details belongs to.
  *
  * @return
  *   The processed element.
  */
-function form_process_fieldset(&$element, &$form_state) {
+function form_process_details(&$element, &$form_state) {
   $parents = implode('][', $element['#parents']);
 
-  // Each fieldset forms a new group. The #type 'vertical_tabs' basically only
-  // injects a new fieldset.
+  // Each details element forms a new group. The #type 'vertical_tabs' basically
+  // only injects a new details element.
   $form_state['groups'][$parents]['#group_exists'] = TRUE;
   $element['#groups'] = &$form_state['groups'];
 
-  // Process vertical tabs group member fieldsets.
+  // Process vertical tabs group member details elements.
   if (isset($element['#group'])) {
-    // Add this fieldset to the defined group (by reference).
+    // Add this details element to the defined group (by reference).
     $group = $element['#group'];
     $form_state['groups'][$group][] = &$element;
   }
@@ -3708,28 +3741,28 @@ function form_process_fieldset(&$element, &$form_state) {
  *
  * @param $element
  *   An associative array containing the properties and children of the
- *   fieldset.
+ *   details.
  *
  * @return
  *   The modified element with all group members.
  */
-function form_pre_render_fieldset($element) {
-  // The .form-wrapper class is required for #states to treat fieldsets like
+function form_pre_render_details($element) {
+  // The .form-wrapper class is required for #states to treat details like
   // containers.
   if (!isset($element['#attributes']['class'])) {
     $element['#attributes']['class'] = array();
   }
 
-  // Collapsible fieldsets
+  // Collapsible details.
   if (!empty($element['#collapsible'])) {
     $element['#attached']['library'][] = array('system', 'drupal.collapse');
     $element['#attributes']['class'][] = 'collapsible';
-    if (!empty($element['#collapsed'])) {
-      $element['#attributes']['class'][] = 'collapsed';
-    }
+  }
+  if (empty($element['#collapsed'])) {
+    $element['#attributes']['open'] = 'open';
   }
 
-  // Fieldsets may be rendered outside of a Form API context.
+  // Details may be rendered outside of a Form API context.
   if (!isset($element['#parents']) || !isset($element['#groups'])) {
     return $element;
   }
@@ -3741,7 +3774,7 @@ function form_pre_render_fieldset($element) {
       // Break references and indicate that the element should be rendered as
       // group member.
       $child = (array) $element['#groups'][$parents][$key];
-      $child['#group_fieldset'] = TRUE;
+      $child['#group_details'] = TRUE;
       // Inject the element as new child element.
       $element[] = $child;
 
@@ -3761,7 +3794,7 @@ function form_pre_render_fieldset($element) {
       // Intentionally empty to clarify the flow; we simply return $element.
     }
     // If we injected this element into the group, then we want to render it.
-    elseif (!empty($element['#group_fieldset'])) {
+    elseif (!empty($element['#group_details'])) {
       // Intentionally empty to clarify the flow; we simply return $element.
     }
     // Otherwise, this element belongs to a group and the group exists, so we do
@@ -3779,7 +3812,7 @@ function form_pre_render_fieldset($element) {
  *
  * @param $element
  *   An associative array containing the properties and children of the
- *   fieldset.
+ *   details element.
  * @param $form_state
  *   The $form_state array for the form this vertical tab widget belongs to.
  *
@@ -3787,10 +3820,10 @@ function form_pre_render_fieldset($element) {
  *   The processed element.
  */
 function form_process_vertical_tabs($element, &$form_state) {
-  // Inject a new fieldset as child, so that form_process_fieldset() processes
-  // this fieldset like any other fieldset.
+  // Inject a new details as child, so that form_process_details() processes
+  // this details element like any other details.
   $element['group'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#theme_wrappers' => array(),
     '#parents' => $element['#parents'],
   );
@@ -3813,12 +3846,12 @@ function form_process_vertical_tabs($element, &$form_state) {
 }
 
 /**
- * Returns HTML for an element's children fieldsets as vertical tabs.
+ * Returns HTML for an element's children details as vertical tabs.
  *
  * @param $variables
  *   An associative array containing:
  *   - element: An associative array containing the properties and children of
- *     the fieldset. Properties used: #children.
+ *     the details element. Properties used: #children.
  *
  * @ingroup themeable
  */
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index ce67e408942a..efeca4816b70 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1880,7 +1880,7 @@ function install_check_requirements($install_state) {
  */
 function _install_configure_form($form, &$form_state, &$install_state) {
   $form['site_information'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => st('Site information'),
     '#collapsible' => FALSE,
   );
@@ -1899,7 +1899,7 @@ function _install_configure_form($form, &$form_state, &$install_state) {
     '#weight' => -15,
   );
   $form['admin_account'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => st('Site maintenance account'),
     '#collapsible' => FALSE,
   );
@@ -1928,7 +1928,7 @@ function _install_configure_form($form, &$form_state, &$install_state) {
   );
 
   $form['server_settings'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => st('Server settings'),
     '#collapsible' => FALSE,
   );
@@ -1955,7 +1955,7 @@ function _install_configure_form($form, &$form_state, &$install_state) {
   );
 
   $form['update_notifications'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => st('Update notifications'),
     '#collapsible' => FALSE,
   );
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index f8b89db59a97..ba6baf2a656b 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -3121,6 +3121,9 @@ function drupal_common_theme() {
     'fieldset' => array(
       'render element' => 'element',
     ),
+    'details' => array(
+      'render element' => 'element',
+    ),
     'radio' => array(
       'render element' => 'element',
     ),
diff --git a/core/lib/Drupal/Core/Database/Install/Tasks.php b/core/lib/Drupal/Core/Database/Install/Tasks.php
index 5d34a62b2633..d7faaec0ee0f 100644
--- a/core/lib/Drupal/Core/Database/Install/Tasks.php
+++ b/core/lib/Drupal/Core/Database/Install/Tasks.php
@@ -232,7 +232,7 @@ public function getFormOptions($database) {
     );
 
     $form['advanced_options'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => st('Advanced options'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
diff --git a/core/lib/Drupal/Core/FileTransfer/FileTransfer.php b/core/lib/Drupal/Core/FileTransfer/FileTransfer.php
index 337b0b3e65a0..72a6751a3f3e 100644
--- a/core/lib/Drupal/Core/FileTransfer/FileTransfer.php
+++ b/core/lib/Drupal/Core/FileTransfer/FileTransfer.php
@@ -406,7 +406,7 @@ public function getSettingsForm() {
       '#description' => t('Your password is not saved in the database and is only used to establish a connection.'),
     );
     $form['advanced'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Advanced settings'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
diff --git a/core/misc/collapse.js b/core/misc/collapse.js
index 80f593975976..3d99bcefef0d 100644
--- a/core/misc/collapse.js
+++ b/core/misc/collapse.js
@@ -3,22 +3,57 @@
 "use strict";
 
 /**
- * The collapsible fieldset object represents a single collapsible fieldset.
+ * Details feature detection.
+ *
+ * @todo This is a stop-gap fix only. collapse.js needs to be replaced with a
+ *   proper HTML5 details polyfill.
+ *
+ * @author Mathias Bynens
+ * @see http://mathiasbynens.be/notes/html5-details-jquery
  */
-function CollapsibleFieldset(node, settings) {
+var isDetailsSupported = (function (doc) {
+  var el = doc.createElement('details'),
+      fake,
+      root,
+      diff;
+  if (!('open' in el)) {
+    return false;
+  }
+  root = doc.body || (function () {
+    var de = doc.documentElement;
+    fake = true;
+    return de.insertBefore(doc.createElement('body'), de.firstElementChild || de.firstChild);
+  }());
+  el.innerHTML = '<summary>a</summary>b';
+  el.style.display = 'block';
+  root.appendChild(el);
+  diff = el.offsetHeight;
+  el.open = true;
+  diff = diff != el.offsetHeight;
+  root.removeChild(el);
+  if (fake) {
+    root.parentNode.removeChild(root);
+  }
+  return diff;
+}(document));
+
+/**
+ * The collapsible details object represents a single collapsible details element.
+ */
+function CollapsibleDetails(node, settings) {
   this.$node = $(node);
-  this.$node.data('fieldset', this);
+  this.$node.data('details', this);
   this.settings = $.extend({
       duration:'fast',
       easing:'linear'
     },
     settings
   );
-  // Expand fieldset if there are errors inside, or if it contains an
+  // Expand details if there are errors inside, or if it contains an
   // element that is targeted by the URI fragment identifier.
   var anchor = location.hash && location.hash !== '#' ? ', ' + location.hash : '';
   if (this.$node.find('.error' + anchor).length) {
-    this.$node.removeClass('collapsed');
+    this.$node.attr('open', true);
   }
   // Initialize and setup the summary,
   this.setupSummary();
@@ -27,19 +62,19 @@ function CollapsibleFieldset(node, settings) {
 }
 
 /**
- * Extend CollapsibleFieldset function.
+ * Extend CollapsibleDetails function.
  */
-$.extend(CollapsibleFieldset, {
+$.extend(CollapsibleDetails, {
   /**
-   * Holds references to instantiated CollapsibleFieldset objects.
+   * Holds references to instantiated CollapsibleDetails objects.
    */
-  fieldsets: []
+  instances: []
 });
 
 /**
- * Extend CollapsibleFieldset prototype.
+ * Extend CollapsibleDetails prototype.
  */
-$.extend(CollapsibleFieldset.prototype, {
+$.extend(CollapsibleDetails.prototype, {
   /**
    * Flag preventing multiple simultaneous animations.
    */
@@ -57,17 +92,16 @@ $.extend(CollapsibleFieldset.prototype, {
    * Initialize and setup legend markup.
    */
   setupLegend: function () {
-    // Turn the legend into a clickable link, but retain span.fieldset-legend
-    // for CSS positioning.
-    var $legend = this.$node.find('> legend .fieldset-legend');
+    // Turn the summary into a clickable link.
+    var $legend = this.$node.find('> summary');
 
-    $('<span class="fieldset-legend-prefix element-invisible"></span>')
-      .append(this.$node.hasClass('collapsed') ? Drupal.t('Show') : Drupal.t('Hide'))
+    $('<span class="details-summary-prefix element-invisible"></span>')
+      .append(this.$node.attr('open') ? Drupal.t('Hide') : Drupal.t('Show'))
       .prependTo($legend)
       .after(' ');
 
     // .wrapInner() does not retain bound events.
-    var $link = $('<a class="fieldset-title" href="#"></a>')
+    var $link = $('<a class="details-title" href="#"></a>')
       .prepend($legend.contents())
       .appendTo($legend)
       .click($.proxy(this.onLegendClick, this));
@@ -88,19 +122,18 @@ $.extend(CollapsibleFieldset.prototype, {
     this.$summary.html(text ? ' (' + text + ')' : '');
   },
   /**
-   * Toggle the visibility of a fieldset using smooth animations.
+   * Toggle the visibility of a details element using smooth animations.
    */
   toggle: function () {
     // Don't animate multiple times.
     if (this.animating) {
       return;
     }
-    if (this.$node.is('.collapsed')) {
-      var $content = this.$node.find('> .fieldset-wrapper').hide();
+    if (!this.$node.attr('open')) {
+      var $content = this.$node.find('> .details-wrapper').hide();
       this.$node
-        .removeClass('collapsed')
         .trigger({ type:'collapsed', value:false })
-        .find('> legend span.fieldset-legend-prefix').html(Drupal.t('Hide'));
+        .find('> summary span.details-summary-prefix').html(Drupal.t('Hide'));
       $content.slideDown(
         $.extend(this.settings, {
           complete:$.proxy(this.onCompleteSlideDown, this)
@@ -109,7 +142,7 @@ $.extend(CollapsibleFieldset.prototype, {
     }
     else {
       this.$node.trigger({ type:'collapsed', value:true });
-      this.$node.find('> .fieldset-wrapper').slideUp(
+      this.$node.find('> .details-wrapper').slideUp(
         $.extend(this.settings, {
           complete:$.proxy(this.onCompleteSlideUp, this)
         })
@@ -117,19 +150,20 @@ $.extend(CollapsibleFieldset.prototype, {
     }
   },
   /**
-   * Completed opening fieldset.
+   * Completed opening details element.
    */
   onCompleteSlideDown: function () {
+    this.$node.attr('open', true);
     this.$node.trigger('completeSlideDown');
     this.animating = false;
   },
   /**
-   * Completed closing fieldset.
+   * Completed closing details element.
    */
   onCompleteSlideUp: function () {
+    this.$node.attr('open', false);
     this.$node
-      .addClass('collapsed')
-      .find('> legend span.fieldset-legend-prefix').html(Drupal.t('Show'));
+      .find('> summary span.details-summary-prefix').html(Drupal.t('Show'));
     this.$node.trigger('completeSlideUp');
     this.animating = false;
   }
@@ -137,16 +171,19 @@ $.extend(CollapsibleFieldset.prototype, {
 
 Drupal.behaviors.collapse = {
   attach: function (context, settings) {
-    var $collapsibleFieldsets = $(context).find('fieldset.collapsible').once('collapse');
-    if ($collapsibleFieldsets.length) {
-      for (var i = 0; i < $collapsibleFieldsets.length; i++) {
-        CollapsibleFieldset.fieldsets.push(new CollapsibleFieldset($collapsibleFieldsets[i], settings.collapsibleFieldset));
+    if (isDetailsSupported) {
+      return;
+    }
+    var $collapsibleDetails = $(context).find('details.collapsible').once('collapse');
+    if ($collapsibleDetails.length) {
+      for (var i = 0; i < $collapsibleDetails.length; i++) {
+        CollapsibleDetails.instances.push(new CollapsibleDetails($collapsibleDetails[i], settings.collapsibleDetails));
       }
     }
   }
 };
 
 // Expose constructor in the public space.
-Drupal.CollapsibleFieldset = CollapsibleFieldset;
+Drupal.CollapsibleDetails = CollapsibleDetails;
 
 })(jQuery, Drupal);
diff --git a/core/misc/states.js b/core/misc/states.js
index afd922c0785c..75ee01dfcace 100644
--- a/core/misc/states.js
+++ b/core/misc/states.js
@@ -420,7 +420,7 @@ states.Trigger.states = {
 
   collapsed: {
     'collapsed': function(e) {
-      return (typeof e !== 'undefined' && 'value' in e) ? e.value : this.is('.collapsed');
+      return (typeof e !== 'undefined' && 'value' in e) ? e.value : !this.is('[open]');
     }
   }
 };
@@ -477,6 +477,8 @@ states.State.aliases = {
   'unchecked': '!checked',
   'irrelevant': '!relevant',
   'expanded': '!collapsed',
+  'open': '!collapsed',
+  'closed': 'collapsed',
   'readwrite': '!readonly'
 };
 
@@ -537,8 +539,8 @@ $(document).bind('state:checked', function(e) {
 
 $(document).bind('state:collapsed', function(e) {
   if (e.trigger) {
-    if ($(e.target).is('.collapsed') !== e.value) {
-      $(e.target).find('> legend a').click();
+    if ($(e.target).is('[open]') === e.value) {
+      $(e.target).find('> summary a').click();
     }
   }
 });
diff --git a/core/misc/vertical-tabs.css b/core/misc/vertical-tabs.css
index c9465037d58f..cf6cca6692cd 100644
--- a/core/misc/vertical-tabs.css
+++ b/core/misc/vertical-tabs.css
@@ -11,12 +11,11 @@ div.vertical-tabs {
   margin: -1px 0 -1px -15em; /* LTR */
   float: left; /* LTR */
 }
-.vertical-tabs fieldset.vertical-tabs-pane {
-  margin: 0 !important;
-  padding: 0 1em;
+.vertical-tabs .vertical-tabs-pane {
+  margin: 0;
   border: 0;
 }
-fieldset.vertical-tabs-pane > legend {
+.vertical-tabs-pane > summary {
   display: none;
 }
 
@@ -62,7 +61,7 @@ fieldset.vertical-tabs-pane > legend {
  * with "box-sizing" to prevent box model issues from occurring in most browsers.
 */
 .vertical-tabs .form-type-textfield input {
-  width: 100%;
+  max-width: 100%;
   -moz-box-sizing: border-box;
   -webkit-box-sizing: border-box;
   box-sizing: border-box;
diff --git a/core/misc/vertical-tabs.js b/core/misc/vertical-tabs.js
index 303840ab551c..6d902e919a80 100644
--- a/core/misc/vertical-tabs.js
+++ b/core/misc/vertical-tabs.js
@@ -3,13 +3,13 @@
 "use strict";
 
 /**
- * This script transforms a set of fieldsets into a stack of vertical
+ * This script transforms a set of details into a stack of vertical
  * tabs. Another tab pane can be selected by clicking on the respective
  * tab.
  *
  * Each tab may have a summary which can be updated by another
- * script. For that to work, each fieldset has an associated
- * 'verticalTabCallback' (with jQuery.data() attached to the fieldset),
+ * script. For that to work, each details element has an associated
+ * 'verticalTabCallback' (with jQuery.data() attached to the details),
  * which is called every time the user performs an update to a form
  * element inside the tab pane.
  */
@@ -25,9 +25,9 @@ Drupal.behaviors.verticalTabs = {
       var focusID = $this.find(':hidden.vertical-tabs-active-tab').val();
       var tab_focus;
 
-      // Check if there are some fieldsets that can be converted to vertical-tabs
-      var $fieldsets = $this.find('> fieldset');
-      if ($fieldsets.length === 0) {
+      // Check if there are some details that can be converted to vertical-tabs
+      var $details = $this.find('> details');
+      if ($details.length === 0) {
         return;
       }
 
@@ -35,16 +35,17 @@ Drupal.behaviors.verticalTabs = {
       var tab_list = $('<ul class="vertical-tabs-list"></ul>');
       $this.wrap('<div class="vertical-tabs clearfix"></div>').before(tab_list);
 
-      // Transform each fieldset into a tab.
-      $fieldsets.each(function () {
+      // Transform each details into a tab.
+      $details.each(function () {
         var $this = $(this);
         var vertical_tab = new Drupal.verticalTab({
-          title: $this.find('> legend').text(),
-          fieldset: $this
+          title: $this.find('> summary').text(),
+          details: $this
         });
         tab_list.append(vertical_tab.item);
         $this
           .removeClass('collapsible collapsed')
+          .attr('open', true)
           .addClass('vertical-tabs-pane')
           .data('verticalTab', vertical_tab);
         if (this.id === focusID) {
@@ -79,7 +80,7 @@ Drupal.behaviors.verticalTabs = {
  * @param settings
  *   An object with the following keys:
  *   - title: The name of the tab.
- *   - fieldset: The jQuery object of the fieldset that is the tab pane.
+ *   - details: The jQuery object of the details element that is the tab pane.
  */
 Drupal.verticalTab = function (settings) {
   var self = this;
@@ -96,12 +97,12 @@ Drupal.verticalTab = function (settings) {
     event.preventDefault();
     if (event.keyCode === 13) {
       self.focus();
-      // Set focus on the first input field of the visible fieldset/tab pane.
-      $("fieldset.vertical-tabs-pane :input:visible:enabled:first").focus();
+      // Set focus on the first input field of the visible details/tab pane.
+      $(".vertical-tabs-pane :input:visible:enabled:first").focus();
     }
   });
 
-  this.fieldset
+  this.details
     .bind('summaryUpdated', function () {
       self.updateSummary();
     })
@@ -113,17 +114,17 @@ Drupal.verticalTab.prototype = {
    * Displays the tab's content pane.
    */
   focus: function () {
-    this.fieldset
-      .siblings('fieldset.vertical-tabs-pane')
+    this.details
+      .siblings('.vertical-tabs-pane')
         .each(function () {
           var tab = $(this).data('verticalTab');
-          tab.fieldset.hide();
+          tab.details.hide();
           tab.item.removeClass('selected');
         })
         .end()
       .show()
       .siblings(':hidden.vertical-tabs-active-tab')
-        .val(this.fieldset.attr('id'));
+        .val(this.details.attr('id'));
     this.item.addClass('selected');
     // Mark the active tab for screen readers.
     $('#active-vertical-tab').remove();
@@ -134,7 +135,7 @@ Drupal.verticalTab.prototype = {
    * Updates the tab's summary.
    */
   updateSummary: function () {
-    this.summary.html(this.fieldset.drupalGetSummary());
+    this.summary.html(this.details.drupalGetSummary());
   },
 
   /**
@@ -148,8 +149,8 @@ Drupal.verticalTab.prototype = {
     // method.
     this.item.parent().children('.vertical-tab-button').removeClass('first')
       .filter(':visible:first').addClass('first');
-    // Display the fieldset.
-    this.fieldset.removeClass('vertical-tab-hidden').show();
+    // Display the details element.
+    this.details.removeClass('vertical-tab-hidden').show();
     // Focus this tab.
     this.focus();
     return this;
@@ -166,10 +167,10 @@ Drupal.verticalTab.prototype = {
     // method.
     this.item.parent().children('.vertical-tab-button').removeClass('first')
       .filter(':visible:first').addClass('first');
-    // Hide the fieldset.
-    this.fieldset.addClass('vertical-tab-hidden').hide();
+    // Hide the details element.
+    this.details.addClass('vertical-tab-hidden').hide();
     // Focus the first visible tab (if there is one).
-    var $firstTab = this.fieldset.siblings('.vertical-tabs-pane:not(.vertical-tab-hidden):first');
+    var $firstTab = this.details.siblings('.vertical-tabs-pane:not(.vertical-tab-hidden):first');
     if ($firstTab.length) {
       $firstTab.data('verticalTab').focus();
     }
diff --git a/core/modules/action/action.admin.inc b/core/modules/action/action.admin.inc
index f130111c0652..c9db258b4860 100644
--- a/core/modules/action/action.admin.inc
+++ b/core/modules/action/action.admin.inc
@@ -96,7 +96,7 @@ function action_admin_manage() {
  */
 function action_admin_manage_form($form, &$form_state, $options = array()) {
   $form['parent'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Create an advanced action'),
     '#attributes' => array('class' => array('container-inline')),
   );
diff --git a/core/modules/aggregator/aggregator.admin.inc b/core/modules/aggregator/aggregator.admin.inc
index a859e85def87..9b9d2bef2ea6 100644
--- a/core/modules/aggregator/aggregator.admin.inc
+++ b/core/modules/aggregator/aggregator.admin.inc
@@ -538,7 +538,7 @@ function aggregator_admin_form($form, $form_state) {
   }
   if (count($basic_conf)) {
     $form['basic_conf'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Basic configuration'),
       '#description' => t('For most aggregation tasks, the default settings are fine.'),
       '#collapsible' => TRUE,
diff --git a/core/modules/aggregator/aggregator.processor.inc b/core/modules/aggregator/aggregator.processor.inc
index b333a963bf55..f00edc531757 100644
--- a/core/modules/aggregator/aggregator.processor.inc
+++ b/core/modules/aggregator/aggregator.processor.inc
@@ -79,10 +79,10 @@ function aggregator_form_aggregator_admin_form_alter(&$form, $form_state) {
     $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
     $period[AGGREGATOR_CLEAR_NEVER] = t('Never');
 
-    // Only wrap into a collapsible fieldset if there is a basic configuration.
+    // Only wrap into a collapsible details if there is a basic configuration.
     if (isset($form['basic_conf'])) {
       $form['modules']['aggregator'] = array(
-        '#type' => 'fieldset',
+        '#type' => 'details',
         '#title' => t('Default processor settings'),
         '#description' => $info['description'],
         '#collapsible' => TRUE,
diff --git a/core/modules/block/block.admin.inc b/core/modules/block/block.admin.inc
index 2a17a5521170..f6322327a4af 100644
--- a/core/modules/block/block.admin.inc
+++ b/core/modules/block/block.admin.inc
@@ -303,7 +303,7 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
 
   // Region settings.
   $form['regions'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Region settings'),
     '#collapsible' => FALSE,
     '#description' => t('Specify in which themes and regions this block is displayed.'),
@@ -355,7 +355,7 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
 
   // Per-path visibility.
   $form['visibility']['path'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Pages'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
@@ -429,7 +429,7 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
       $langcodes_options[$language->langcode] = $language->name;
     }
     $form['visibility']['language'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Languages'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
@@ -467,7 +467,7 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
   ))->fetchCol();
   $role_options = array_map('check_plain', user_roles());
   $form['visibility']['role'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Roles'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
@@ -484,7 +484,7 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
 
   // Per-user visibility.
   $form['visibility']['user'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Users'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 7340c6bb8719..20191b70052c 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -611,10 +611,10 @@ function block_form_user_profile_form_alter(&$form, &$form_state) {
       );
     }
   }
-  // Only display the fieldset if there are any personalizable blocks.
+  // Only display the form element if there are any personalizable blocks.
   if ($blocks) {
     $form['block'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Personalize blocks'),
       '#description' => t('Blocks consist of content or information that complements the main content of the page. Enable or disable optional blocks using the checkboxes below.'),
       '#weight' => 3,
diff --git a/core/modules/book/book.js b/core/modules/book/book.js
index 301c67ff1042..d1c54c86ceb2 100644
--- a/core/modules/book/book.js
+++ b/core/modules/book/book.js
@@ -8,9 +8,9 @@
 
 "use strict";
 
-Drupal.behaviors.bookFieldsetSummaries = {
+Drupal.behaviors.bookDetailsSummaries = {
   attach: function (context) {
-    $(context).find('fieldset.book-outline-form').drupalSetSummary(function (context) {
+    $(context).find('.book-outline-form').drupalSetSummary(function (context) {
       var $select = $(context).find('.book-title-select');
       var val = $select.val();
 
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index 062097aeaa8f..c661809d6d83 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -397,7 +397,7 @@ function book_get_books() {
 /**
  * Implements hook_form_BASE_FORM_ID_alter() for node_form().
  *
- * Adds the book fieldset to the node form.
+ * Adds the book form element to the node form.
  *
  * @see book_pick_book_nojs_submit()
  */
@@ -513,7 +513,7 @@ function _book_add_form_elements(&$form, &$form_state, Node $node) {
   }
 
   $form['book'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Book outline'),
     '#weight' => 10,
     '#collapsible' => TRUE,
diff --git a/core/modules/color/color.module b/core/modules/color/color.module
index 56c04cf40903..53a7f39858cc 100644
--- a/core/modules/color/color.module
+++ b/core/modules/color/color.module
@@ -39,7 +39,7 @@ function color_theme() {
 function color_form_system_theme_settings_alter(&$form, &$form_state) {
   if (isset($form_state['build_info']['args'][0]) && ($theme = $form_state['build_info']['args'][0]) && color_get_info($theme) && function_exists('gd_info')) {
     $form['color'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Color scheme'),
       '#weight' => -1,
       '#attributes' => array('id' => 'color_scheme_form'),
diff --git a/core/modules/comment/comment-node-form.js b/core/modules/comment/comment-node-form.js
index 0249d96dadc8..67800dada4af 100644
--- a/core/modules/comment/comment-node-form.js
+++ b/core/modules/comment/comment-node-form.js
@@ -7,15 +7,15 @@
 
 "use strict";
 
-Drupal.behaviors.commentFieldsetSummaries = {
+Drupal.behaviors.commentDetailsSummaries = {
   attach: function (context) {
     var $context = $(context);
-    $context.find('fieldset.comment-node-settings-form').drupalSetSummary(function (context) {
+    $context.find('.comment-node-settings-form').drupalSetSummary(function (context) {
       return Drupal.checkPlain($(context).find('.form-item-comment input:checked').next('label').text());
     });
 
     // Provide the summary for the node type form.
-    $context.find('fieldset.comment-node-type-settings-form').drupalSetSummary(function(context) {
+    $context.find('.comment-node-type-settings-form').drupalSetSummary(function(context) {
       var $context = $(context);
       var vals = [];
 
diff --git a/core/modules/comment/comment.admin.inc b/core/modules/comment/comment.admin.inc
index 52d1740e0bfa..e0a0165df009 100644
--- a/core/modules/comment/comment.admin.inc
+++ b/core/modules/comment/comment.admin.inc
@@ -44,7 +44,7 @@ function comment_admin($type = 'new') {
 function comment_admin_overview($form, &$form_state, $arg) {
   // Build an 'Update options' form.
   $form['options'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Update options'),
     '#attributes' => array('class' => array('container-inline')),
   );
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 38adbd06bb31..cac428fbe3ee 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1048,7 +1048,7 @@ function comment_view_multiple($comments, $view_mode = 'full', $langcode = NULL)
 function comment_form_node_type_form_alter(&$form, $form_state) {
   if (isset($form['type'])) {
     $form['comment'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Comment settings'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
@@ -1154,7 +1154,7 @@ function comment_translation_configuration_element_submit($form, &$form_state) {
 function comment_form_node_form_alter(&$form, $form_state) {
   $node = $form_state['controller']->getEntity($form_state);
   $form['comment_settings'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#access' => user_access('administer comments'),
     '#title' => t('Comment settings'),
     '#collapsible' => TRUE,
diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php
index 10c6b479bef3..db1588919942 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php
@@ -50,10 +50,10 @@ public function form(array $form, array &$form_state, EntityInterface $comment)
     $form['author'] = array(
       '#weight' => 10,
     );
-    // Display author information in a fieldset for comment moderators.
+    // Display author information in a details element for comment moderators.
     if ($is_admin) {
       $form['author'] += array(
-        '#type' => 'fieldset',
+        '#type' => 'details',
         '#title' => t('Administration'),
         '#collapsible' => TRUE,
         '#collapsed' => TRUE,
diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module
index 585f0118e9b7..4e1ec6b42107 100644
--- a/core/modules/contact/contact.module
+++ b/core/modules/contact/contact.module
@@ -284,7 +284,7 @@ function contact_mail($key, &$message, $params) {
  */
 function contact_form_user_profile_form_alter(&$form, &$form_state) {
   $form['contact'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Contact settings'),
     '#weight' => 5,
     '#collapsible' => TRUE,
@@ -314,7 +314,7 @@ function contact_user_presave($account) {
  */
 function contact_form_user_admin_settings_alter(&$form, &$form_state) {
   $form['contact'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Contact settings'),
     '#weight' => 0,
   );
diff --git a/core/modules/dblog/dblog.admin.inc b/core/modules/dblog/dblog.admin.inc
index edef5fb13c77..d6b921a48805 100644
--- a/core/modules/dblog/dblog.admin.inc
+++ b/core/modules/dblog/dblog.admin.inc
@@ -318,7 +318,7 @@ function dblog_filter_form($form) {
   $filters = dblog_filters();
 
   $form['filters'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Filter log messages'),
     '#collapsible' => TRUE,
     '#collapsed' => empty($_SESSION['dblog_overview_filter']),
@@ -395,7 +395,7 @@ function dblog_filter_form_submit($form, &$form_state) {
  */
 function dblog_clear_log_form($form) {
   $form['dblog_clear'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Clear log messages'),
     '#description' => t('This will permanently remove the log messages from the database.'),
     '#collapsible' => TRUE,
diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
index 005eb14235c2..4c56bff74245 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
@@ -451,7 +451,7 @@ function multiple_options_form(&$form, &$form_state) {
     $field = $this->field_info;
 
     $form['multiple_field_settings'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Multiple field settings'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
diff --git a/core/modules/field/tests/modules/field_test/field_test.entity.inc b/core/modules/field/tests/modules/field_test/field_test.entity.inc
index b48f5cf5c611..14285a755d5a 100644
--- a/core/modules/field/tests/modules/field_test/field_test.entity.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.entity.inc
@@ -202,7 +202,7 @@ function field_test_entity_nested_form($form, &$form_state, $entity_1, $entity_2
 
   // Second entity.
   $form['entity_2'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Second entity'),
     '#tree' => TRUE,
     '#parents' => array('entity_2'),
diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc
index c93aa03021b6..0ddaf5a5e14d 100644
--- a/core/modules/field_ui/field_ui.admin.inc
+++ b/core/modules/field_ui/field_ui.admin.inc
@@ -562,7 +562,7 @@ function field_ui_field_settings_form($form, &$form_state, $instance) {
 
   // Create a form structure for the field values.
   $form['field'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Field settings'),
     '#description' => $description,
     '#tree' => TRUE,
@@ -656,7 +656,7 @@ function field_ui_widget_type_form($form, &$form_state, FieldInstance $instance)
   );
 
   $form['basic'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Change widget'),
   );
   $form['basic']['widget_type'] = array(
@@ -815,15 +815,15 @@ function field_ui_field_edit_form($form, &$form_state, $instance) {
   // Create a form structure for the instance values.
   $form['instance'] = array(
     '#tree' => TRUE,
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('%type settings', array('%type' => $bundles[$entity_type][$bundle]['label'])),
     '#description' => t('These settings apply only to the %field field when used in the %type type.', array(
       '%field' => $instance['label'],
       '%type' => $bundles[$entity_type][$bundle]['label'],
     )),
     // Ensure field_ui_field_edit_instance_pre_render() gets called in addition
-    // to, not instead of, the #pre_render function(s) needed by all fieldsets.
-    '#pre_render' => array_merge(array('field_ui_field_edit_instance_pre_render'), element_info_property('fieldset', '#pre_render', array())),
+    // to, not instead of, the #pre_render function(s) needed by all details.
+    '#pre_render' => array_merge(array('field_ui_field_edit_instance_pre_render'), element_info_property('details', '#pre_render', array())),
   );
 
   // Build the non-configurable instance values.
@@ -908,7 +908,7 @@ function field_ui_field_edit_form($form, &$form_state, $instance) {
 
   // Create a form structure for the field values.
   $form['field'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
     '#title' => t('Global settings'),
@@ -966,7 +966,7 @@ function field_ui_field_edit_form_delete_submit($form, &$form_state) {
 /**
  * Render API callback: Merges instance, widget and other settings.
  *
- * Combines the instance, widget, and other settings into a single fieldset so
+ * Combines the instance, widget, and other settings into a single details so
  * that elements within each group can be shown at different weights as if they
  * all had the same parent.
  *
@@ -994,14 +994,14 @@ function field_ui_field_edit_instance_pre_render($element) {
 }
 
 /**
- * Builds the default value fieldset for a given field instance.
+ * Builds the default value widget for a given field instance.
  */
 function field_ui_default_value_widget($field, $instance, &$form, &$form_state) {
   $field_name = $field['field_name'];
   $entity = $form['#entity'];
 
   $element = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Default value'),
     '#collapsible' => FALSE,
     '#tree' => TRUE,
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
index a777f3e7a6c4..6117de97a5c7 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
@@ -348,7 +348,7 @@ public function form(array $form, array &$form_state) {
       // Only show the settings if there is more than one view mode.
       if (count($view_modes) > 1) {
         $form['modes'] = array(
-          '#type' => 'fieldset',
+          '#type' => 'details',
           '#title' => t('Custom display settings'),
           '#collapsible' => TRUE,
           '#collapsed' => TRUE,
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
index c0c8eb5f85db..98a7a9613371 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
@@ -142,7 +142,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
       // building up the full list (like draggable table rows).
       $elements['#file_upload_delta'] = $delta;
       $elements['#theme'] = 'file_widget_multiple';
-      $elements['#theme_wrappers'] = array('fieldset');
+      $elements['#theme_wrappers'] = array('details');
       $elements['#process'] = array('file_field_widget_process_multiple');
       $elements['#title'] = $title;
 
diff --git a/core/modules/filter/filter.admin-rtl.css b/core/modules/filter/filter.admin-rtl.css
index c49481bf680c..10620bfac531 100644
--- a/core/modules/filter/filter.admin-rtl.css
+++ b/core/modules/filter/filter.admin-rtl.css
@@ -7,10 +7,6 @@
 /**
  * Filter information under field.
  */
-.filter-wrapper .form-item {
-  float: right;
-  padding: 0 1.5em 0.5em 0;
-}
 .filter-help {
   float: left;
 }
diff --git a/core/modules/filter/filter.admin.css b/core/modules/filter/filter.admin.css
index fdb2effa89ce..2ee792a614fa 100644
--- a/core/modules/filter/filter.admin.css
+++ b/core/modules/filter/filter.admin.css
@@ -7,18 +7,18 @@
 /**
  * Filter information under field.
  */
-.text-format-wrapper .form-item {
+.text-format-wrapper > .form-item {
   margin-bottom: 0;
 }
 
 .filter-wrapper {
+  border: 1px solid #ccc;
   border-top: 0;
   margin: 0;
-  padding: 1.5em 0;
+  padding: 0.5em 1.5em;
 }
 .filter-wrapper .form-item {
-  float: left; /* LTR */
-  padding: 0 0 0.5em 1.5em; /* LTR */
+  margin-top: 0;
 }
 .filter-wrapper .form-item label {
   display: inline;
@@ -26,7 +26,6 @@
 
 .filter-help {
   float: right; /* LTR */
-  padding: 0 1.5em 0.5em;
 }
 .filter-help p {
   margin: 0;
@@ -36,10 +35,6 @@
   padding: 0 20px;
 }
 
-.filter-guidelines {
-  clear: left;
-  padding: 0 1.5em;
-}
 .text-format-wrapper .description {
   margin-top: 0.5em;
 }
diff --git a/core/modules/filter/filter.admin.inc b/core/modules/filter/filter.admin.inc
index 4f56856a46ed..c01fb937eae7 100644
--- a/core/modules/filter/filter.admin.inc
+++ b/core/modules/filter/filter.admin.inc
@@ -284,7 +284,7 @@ function filter_admin_format_form($form, &$form_state, $format) {
       $settings_form = $function($form, $form_state, $filters[$name], $format, $defaults, $filters);
       if (!empty($settings_form)) {
         $form['filters']['settings'][$name] = array(
-          '#type' => 'fieldset',
+          '#type' => 'details',
           '#title' => $filter['title'],
           '#parents' => array('filters', $name, 'settings'),
           '#weight' => $filter['weight'],
diff --git a/core/modules/filter/filter.admin.js b/core/modules/filter/filter.admin.js
index b2d7c6ea6554..f55159adf5bd 100644
--- a/core/modules/filter/filter.admin.js
+++ b/core/modules/filter/filter.admin.js
@@ -38,7 +38,7 @@ Drupal.behaviors.filterStatus = {
 
       // Attach summary for configurable filters (only for screen-readers).
       if (tab) {
-        tab.fieldset.drupalSetSummary(function (tabContext) {
+        tab.details.drupalSetSummary(function (tabContext) {
           return $checkbox.is(':checked') ? Drupal.t('Enabled') : Drupal.t('Disabled');
         });
       }
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 2af53f8af44a..947686069e4e 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -53,7 +53,7 @@ function filter_help($path, $arg) {
       $output .= '<dt>' . t('Defining text formats') . '</dt>';
       $output .= '<dd>' . t('One format is included by default: <em>Plain text</em> (which removes all HTML tags). Additional formats may be created by your installation profile when you install Drupal, and more can be created by an administrator on the <a href="@text-formats">Text formats page</a>.', array('@text-formats' => url('admin/config/content/formats'))) . '</dd>';
       $output .= '<dt>' . t('Choosing a text format') . '</dt>';
-      $output .= '<dd>' . t('Users with access to more than one text format can use the <em>Text format</em> fieldset to choose between available text formats when creating or editing multi-line content. Administrators can define the text formats available to each user role, and control the order of formats listed in the <em>Text format</em> fieldset on the <a href="@text-formats">Text formats page</a>.', array('@text-formats' => url('admin/config/content/formats'))) . '</dd>';
+      $output .= '<dd>' . t('Users with access to more than one text format can use the <em>Text format</em> widget to choose between available text formats when creating or editing multi-line content. Administrators can define the text formats available to each user role, and control the order of formats listed in the <em>Text format</em> widget on the <a href="@text-formats">Text formats page</a>.', array('@text-formats' => url('admin/config/content/formats'))) . '</dd>';
       $output .= '</dl>';
       return $output;
 
@@ -905,7 +905,7 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE,
  * selector:
  * - value: Holds the original element, having its #type changed to the value
  *   of #base_type or 'textarea' by default.
- * - format: Holds the text format fieldset and the text format selection,
+ * - format: Holds the text format details and the text format selection,
  *   using the text format ID specified in #format or the user's default format
  *   by default, if NULL.
  *
@@ -967,7 +967,7 @@ function filter_process_format($element) {
 
   // Setup child container for the text format widget.
   $element['format'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'container',
     '#attributes' => array('class' => array('filter-wrapper')),
   );
 
@@ -1083,7 +1083,7 @@ function filter_form_access_denied($element) {
  */
 function theme_text_format_wrapper($variables) {
   $element = $variables['element'];
-  $output = '<div class="text-format-wrapper">';
+  $output = '<div class="text-format-wrapper form-item">';
   $output .= $element['#children'];
   if (!empty($element['#description'])) {
     $output .= '<div class="description">' . $element['#description'] . '</div>';
diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
index a5e5effaf9ce..9bd703bbf46a 100644
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
@@ -312,9 +312,9 @@ private function doAdminTests($user) {
     // Test tags vocabulary term form is not affected.
     $this->drupalGet('admin/structure/taxonomy/tags/add');
     $this->assertField('parent[]', 'Parent field found.');
-    // Test relations fieldset exists.
-    $relations_fieldset = $this->xpath("//fieldset[@id='edit-relations']");
-    $this->assertTrue(isset($relations_fieldset[0]), 'Relations fieldset element found.');
+    // Test relations widget exists.
+    $relations_widget = $this->xpath("//details[@id='edit-relations']");
+    $this->assertTrue(isset($relations_widget[0]), 'Relations widget element found.');
   }
 
   /**
diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index a92793d72d33..4cdcf51d0a30 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -650,7 +650,7 @@ function language_negotiation_configure_url_form($form, &$form_state) {
   );
 
   $form['prefix'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#tree' => TRUE,
     '#title' => t('Path prefix configuration'),
     '#description' => t('Language codes or other custom text to use as a path prefix for URL language detection. For the default language, this value may be left blank. <strong>Modifying this value may break existing URLs. Use with caution in a production environment.</strong> Example: Specifying "deutsch" as the path prefix code for German results in URLs like "example.com/deutsch/contact".'),
@@ -663,7 +663,7 @@ function language_negotiation_configure_url_form($form, &$form_state) {
     ),
   );
   $form['domain'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#tree' => TRUE,
     '#title' => t('Domain configuration'),
     '#description' => t('The domain names to use for these languages. Leave blank for the default language. Use with caution in a production environment.<strong>Modifying this value may break existing URLs. Use with caution in a production environment.</strong> Example: Specifying "de.example.com" as language domain for German will result in an URL like "http://de.example.com/contact".'),
@@ -882,7 +882,7 @@ function language_negotiation_configure_browser_form($form, &$form_state) {
 
   // Add empty row.
   $form['new_mapping'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Add a new mapping'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
index 0302ba964d18..bc74778e32bf 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
@@ -87,7 +87,7 @@ function testContentTypeLanguageConfiguration() {
 
     // Set the content type to use multilingual support.
     $this->drupalGet("admin/structure/types/manage/{$type2->type}");
-    $this->assertText(t('Language settings'), 'Multilingual support fieldset present on content type configuration form.');
+    $this->assertText(t('Language settings'), 'Multilingual support widget present on content type configuration form.');
     $edit = array(
       'language_configuration[language_hidden]' => FALSE,
     );
diff --git a/core/modules/locale/locale.admin.css b/core/modules/locale/locale.admin.css
index f7f2f73128e7..2452608cf8c5 100644
--- a/core/modules/locale/locale.admin.css
+++ b/core/modules/locale/locale.admin.css
@@ -1,3 +1,6 @@
+.locale-translate-filter-form .details-wrapper {
+  overflow: hidden;
+}
 .locale-translate-filter-form .form-item-langcode,
 .locale-translate-filter-form .form-item-translation,
 .locale-translate-filter-form .form-item-customized {
@@ -16,7 +19,7 @@
 }
 .locale-translate-filter-form .form-actions {
   float: left; /* LTR */
-  padding: 3.5ex 0 0 0; /* LTR */
+  padding: 3.8ex 0 0 0; /* LTR */
 }
 .locale-translate-edit-form th {
   width: 50%;
@@ -41,10 +44,6 @@
   margin-bottom:0;
 }
 
-.locale-translate-edit-form .locale-translate-edit-table {
-  margin-top: 54px;
-}
-
 .locale-translate-edit-form table.changed {
   margin-top: 0;
 }
diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc
index 0be2aec0ac46..d29cf6fcd3ea 100644
--- a/core/modules/locale/locale.bulk.inc
+++ b/core/modules/locale/locale.bulk.inc
@@ -174,7 +174,7 @@ function locale_translate_export_form($form, &$form_state) {
       '#empty_value' => LANGUAGE_SYSTEM,
     );
     $form['content_options'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Export options'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index 8ea87805d7fa..72f1793c6543 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -167,7 +167,7 @@ function locale_translate_filter_form($form, &$form_state) {
   );
 
   $form['filters'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Filter translatable strings'),
     '#collapsible' => TRUE,
     '#collapsed' => FALSE,
diff --git a/core/modules/menu/menu.admin.js b/core/modules/menu/menu.admin.js
index d6a228ab1007..530c8b631b7c 100644
--- a/core/modules/menu/menu.admin.js
+++ b/core/modules/menu/menu.admin.js
@@ -13,10 +13,10 @@ Drupal.behaviors.menuChangeParentItems = {
  * Function to set the options of the menu parent item dropdown.
  */
 Drupal.menuUpdateParentList = function () {
-  var $menuFieldset = $('#edit-menu');
+  var $menu = $('#edit-menu');
   var values = [];
 
-  $menuFieldset.find('input:checked').each(function () {
+  $menu.find('input:checked').each(function () {
     // Get the names of all checked menus.
     values.push(Drupal.checkPlain($.trim($(this).val())));
   });
diff --git a/core/modules/menu/menu.js b/core/modules/menu/menu.js
index 1990374461ec..77baddbb68c1 100644
--- a/core/modules/menu/menu.js
+++ b/core/modules/menu/menu.js
@@ -2,9 +2,9 @@
 
 "use strict";
 
-Drupal.behaviors.menuFieldsetSummaries = {
+Drupal.behaviors.menuDetailsSummaries = {
   attach: function (context) {
-    $(context).find('fieldset.menu-link-form').drupalSetSummary(function (context) {
+    $(context).find('.menu-link-form').drupalSetSummary(function (context) {
       var $context = $(context);
       if ($context.find('.form-item-menu-enabled input').is(':checked')) {
         return Drupal.checkPlain($context.find('.form-item-menu-link-title input').val());
@@ -22,7 +22,7 @@ Drupal.behaviors.menuFieldsetSummaries = {
 Drupal.behaviors.menuLinkAutomaticTitle = {
   attach: function (context) {
     var $context = $(context);
-    $context.find('fieldset.menu-link-form').each(function () {
+    $context.find('.menu-link-form').each(function () {
       var $this = $(this);
       // Try to find menu settings widget elements as well as a 'title' field in
       // the form, but play nicely with user permissions and form alterations.
@@ -53,7 +53,7 @@ Drupal.behaviors.menuLinkAutomaticTitle = {
           $link_title.val('');
           $link_title.removeData('menuLinkAutomaticTitleOveridden');
         }
-        $checkbox.closest('fieldset.vertical-tabs-pane').trigger('summaryUpdated');
+        $checkbox.closest('.vertical-tabs-pane').trigger('summaryUpdated');
         $checkbox.trigger('formUpdated');
       });
       // Take over any title change.
diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module
index 73e4380b74ca..e9080fde9042 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -645,7 +645,7 @@ function menu_form_node_form_alter(&$form, $form_state) {
   }
 
   $form['menu'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Menu settings'),
     '#access' => user_access('administer menu'),
     '#collapsible' => TRUE,
@@ -752,7 +752,7 @@ function menu_form_node_type_form_alter(&$form, $form_state) {
   $menu_options = menu_get_menus();
   $type = $form['#node_type'];
   $form['menu'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Menu settings'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
diff --git a/core/modules/node/content_types.inc b/core/modules/node/content_types.inc
index 999de7ffe240..538b19f94d04 100644
--- a/core/modules/node/content_types.inc
+++ b/core/modules/node/content_types.inc
@@ -154,7 +154,7 @@ function node_type_form($form, &$form_state, $type = NULL) {
   );
 
   $form['submission'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Submission form settings'),
     '#collapsible' => TRUE,
     '#group' => 'additional_settings',
@@ -189,7 +189,7 @@ function node_type_form($form, &$form_state, $type = NULL) {
     '#description' => t('This text will be displayed at the top of the page when creating or editing content of this type.'),
   );
   $form['workflow'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Publishing options'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
@@ -208,7 +208,7 @@ function node_type_form($form, &$form_state, $type = NULL) {
   );
   if (module_exists('language')) {
     $form['language'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Language settings'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
@@ -228,7 +228,7 @@ function node_type_form($form, &$form_state, $type = NULL) {
     $form['#submit'][] = 'language_configuration_element_submit';
   }
   $form['display'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Display settings'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
diff --git a/core/modules/node/content_types.js b/core/modules/node/content_types.js
index 787f79542380..40d6422c6687 100644
--- a/core/modules/node/content_types.js
+++ b/core/modules/node/content_types.js
@@ -11,12 +11,12 @@ Drupal.behaviors.contentTypes = {
   attach: function (context) {
     var $context = $(context);
     // Provide the vertical tab summaries.
-    $context.find('fieldset#edit-submission').drupalSetSummary(function(context) {
+    $context.find('#edit-submission').drupalSetSummary(function(context) {
       var vals = [];
       vals.push(Drupal.checkPlain($(context).find('#edit-title-label').val()) || Drupal.t('Requires a title'));
       return vals.join(', ');
     });
-    $context.find('fieldset#edit-workflow').drupalSetSummary(function(context) {
+    $context.find('#edit-workflow').drupalSetSummary(function(context) {
       var vals = [];
       $(context).find("input[name^='node_options']:checked").parent().each(function() {
         vals.push(Drupal.checkPlain($(this).text()));
@@ -26,7 +26,7 @@ Drupal.behaviors.contentTypes = {
       }
       return vals.join(', ');
     });
-    $('fieldset#edit-language', context).drupalSetSummary(function(context) {
+    $('#edit-language', context).drupalSetSummary(function(context) {
       var vals = [];
 
       vals.push($(".form-item-language-configuration-langcode select option:selected", context).text());
@@ -37,7 +37,7 @@ Drupal.behaviors.contentTypes = {
 
       return vals.join(', ');
     });
-    $context.find('fieldset#edit-display').drupalSetSummary(function(context) {
+    $context.find('#edit-display').drupalSetSummary(function(context) {
       var vals = [];
       var $context = $(context);
       $context.find('input:checked').next('label').each(function() {
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index 215ad81e4a9d..43456c7bbd57 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -116,7 +116,7 @@ public function form(array $form, array &$form_state, EntityInterface $node) {
     // Add a log field if the "Create new revision" option is checked, or if the
     // current user has the ability to check that option.
     $form['revision_information'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Revision information'),
       '#collapsible' => TRUE,
       // Collapsed by default when "Create new revision" is unchecked.
@@ -160,7 +160,7 @@ public function form(array $form, array &$form_state, EntityInterface $node) {
 
     // Node author information for administrators.
     $form['author'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#access' => user_access('administer nodes'),
       '#title' => t('Authoring information'),
       '#collapsible' => TRUE,
@@ -201,7 +201,7 @@ public function form(array $form, array &$form_state, EntityInterface $node) {
 
     // Node options for administrators.
     $form['options'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#access' => user_access('administer nodes'),
       '#title' => t('Publishing options'),
       '#collapsible' => TRUE,
diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc
index e171b75a714f..8a49c9c89565 100644
--- a/core/modules/node/node.admin.inc
+++ b/core/modules/node/node.admin.inc
@@ -166,7 +166,7 @@ function node_filter_form() {
 
   $i = 0;
   $form['filters'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Show only items where'),
     '#theme' => 'exposed_filters__node',
   );
@@ -431,7 +431,7 @@ function node_admin_nodes() {
 
   // Build the 'Update options' form.
   $form['options'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Update options'),
     '#attributes' => array('class' => array('container-inline')),
     '#access' => $admin_access,
diff --git a/core/modules/node/node.js b/core/modules/node/node.js
index 7d5688c9a2b8..cdc8cbe57c6f 100644
--- a/core/modules/node/node.js
+++ b/core/modules/node/node.js
@@ -7,10 +7,10 @@
 
 "use strict";
 
-Drupal.behaviors.nodeFieldsetSummaries = {
+Drupal.behaviors.nodeDetailsSummaries = {
   attach: function (context) {
     var $context = $(context);
-    $context.find('fieldset.node-form-revision-information').drupalSetSummary(function (context) {
+    $context.find('.node-form-revision-information').drupalSetSummary(function (context) {
       var $context = $(context);
       var revisionCheckbox = $context.find('.form-item-revision input');
 
@@ -25,7 +25,7 @@ Drupal.behaviors.nodeFieldsetSummaries = {
       return Drupal.t('No revision');
     });
 
-    $context.find('fieldset.node-form-author').drupalSetSummary(function (context) {
+    $context.find('.node-form-author').drupalSetSummary(function (context) {
       var $context = $(context);
       var name = $context.find('.form-item-name input').val() || Drupal.settings.anonymous,
         date = $context.find('.form-item-date input').val();
@@ -34,7 +34,7 @@ Drupal.behaviors.nodeFieldsetSummaries = {
         Drupal.t('By @name', { '@name': name });
     });
 
-    $context.find('fieldset.node-form-options').drupalSetSummary(function (context) {
+    $context.find('.node-form-options').drupalSetSummary(function (context) {
       var $context = $(context);
       var vals = [];
 
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 71a57f2b388a..bdfae92ca3ca 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1302,7 +1302,7 @@ function node_search_status() {
 function node_search_admin() {
   // Output form for defining rank factor weights.
   $form['content_ranking'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Content ranking'),
   );
   $form['content_ranking']['#theme'] = 'node_search_admin';
@@ -2061,7 +2061,7 @@ function node_form_block_admin_configure_alter(&$form, &$form_state) {
     ':delta' => $form['delta']['#value'],
   ))->fetchCol();
   $form['visibility']['node_type'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Content types'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
@@ -2462,7 +2462,7 @@ function node_form_search_form_alter(&$form, $form_state) {
   if (isset($form['module']) && $form['module']['#value'] == 'node' && user_access('use advanced search')) {
     // Keyword boxes:
     $form['advanced'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Advanced search'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module
index 8e6e65b6c180..06214b2d825e 100644
--- a/core/modules/overlay/overlay.module
+++ b/core/modules/overlay/overlay.module
@@ -88,7 +88,7 @@ function overlay_form_user_profile_form_alter(&$form, &$form_state) {
   $account = $form_state['controller']->getEntity($form_state);
   if (user_access('access overlay', $account)) {
     $form['overlay_control'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Administrative overlay'),
       '#weight' => 4,
       '#collapsible' => TRUE,
diff --git a/core/modules/path/path.admin.inc b/core/modules/path/path.admin.inc
index 8c87dee0f55a..05354544bdc3 100644
--- a/core/modules/path/path.admin.inc
+++ b/core/modules/path/path.admin.inc
@@ -303,7 +303,7 @@ function path_admin_delete_confirm_submit($form, &$form_state) {
  */
 function path_admin_filter_form($form, &$form_state, $keys = '') {
   $form['#attributes'] = array('class' => array('search-form'));
-  $form['basic'] = array('#type' => 'fieldset',
+  $form['basic'] = array('#type' => 'details',
     '#title' => t('Filter aliases'),
     '#attributes' => array('class' => array('container-inline')),
   );
diff --git a/core/modules/path/path.js b/core/modules/path/path.js
index 41b6e8f8e9b3..7349d12dc47c 100644
--- a/core/modules/path/path.js
+++ b/core/modules/path/path.js
@@ -6,9 +6,9 @@
 
 "use strict";
 
-Drupal.behaviors.pathFieldsetSummaries = {
+Drupal.behaviors.pathDetailsSummaries = {
   attach: function (context) {
-    $(context).find('fieldset.path-form').drupalSetSummary(function (context) {
+    $(context).find('.path-form').drupalSetSummary(function (context) {
       var path = $('.form-item-path-alias input').val();
 
       return path ?
diff --git a/core/modules/path/path.module b/core/modules/path/path.module
index dcbe3be888e4..63e5c6c06499 100644
--- a/core/modules/path/path.module
+++ b/core/modules/path/path.module
@@ -120,7 +120,7 @@ function path_form_node_form_alter(&$form, $form_state) {
   );
 
   $form['path'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('URL path settings'),
     '#collapsible' => TRUE,
     '#collapsed' => empty($path['alias']),
diff --git a/core/modules/poll/poll.module b/core/modules/poll/poll.module
index d3f8d3a4c542..d1c609365e57 100644
--- a/core/modules/poll/poll.module
+++ b/core/modules/poll/poll.module
@@ -318,7 +318,7 @@ function poll_form(Node $node, &$form_state) {
   $active = array(0 => t('Closed'), 1 => t('Active'));
 
   $form['settings'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#collapsible' => TRUE,
     '#title' => t('Poll settings'),
     '#weight' => -3,
diff --git a/core/modules/search/search.admin.inc b/core/modules/search/search.admin.inc
index 57e5d6bc7507..ef70eb76d643 100644
--- a/core/modules/search/search.admin.inc
+++ b/core/modules/search/search.admin.inc
@@ -61,7 +61,7 @@ function search_admin_settings($form, &$form_state) {
   $count = format_plural($remaining, 'There is 1 item left to index.', 'There are @count items left to index.');
   $percentage = ((int)min(100, 100 * ($total - $remaining) / max(1, $total))) . '%';
   $status = '<p><strong>' . t('%percentage of the site has been indexed.', array('%percentage' => $percentage)) . ' ' . $count . '</strong></p>';
-  $form['status'] = array('#type' => 'fieldset', '#title' => t('Indexing status'));
+  $form['status'] = array('#type' => 'details', '#title' => t('Indexing status'));
   $form['status']['status'] = array('#markup' => $status);
   $form['status']['wipe'] = array('#type' => 'submit', '#value' => t('Re-index site'), '#submit' => array('search_admin_reindex_submit'));
 
@@ -69,7 +69,7 @@ function search_admin_settings($form, &$form_state) {
 
   // Indexing throttle:
   $form['indexing_throttle'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Indexing throttle')
   );
   $form['indexing_throttle']['cron_limit'] = array(
@@ -81,7 +81,7 @@ function search_admin_settings($form, &$form_state) {
   );
   // Indexing settings:
   $form['indexing_settings'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Indexing settings')
   );
   $form['indexing_settings']['info'] = array(
@@ -103,7 +103,7 @@ function search_admin_settings($form, &$form_state) {
   );
 
   $form['active'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Active search modules')
   );
   $module_options = _search_get_module_names();
diff --git a/core/modules/search/search.api.php b/core/modules/search/search.api.php
index be6dd4d435ae..6429f7a85320 100644
--- a/core/modules/search/search.api.php
+++ b/core/modules/search/search.api.php
@@ -133,7 +133,7 @@ function hook_search_status() {
 function hook_search_admin() {
   // Output form for defining rank factor weights.
   $form['content_ranking'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Content ranking'),
   );
   $form['content_ranking']['#theme'] = 'node_search_admin';
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php
index 8abc198c725c..8db5bde2afb6 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/SimpleTestTest.php
@@ -276,13 +276,13 @@ function assertAssertion($message, $type, $status, $file, $function) {
   function getTestResults() {
     $results = array();
     if ($this->parse()) {
-      if ($fieldset = $this->getResultFieldSet()) {
+      if ($details = $this->getResultFieldSet()) {
         // Code assumes this is the only test in group.
-        $results['summary'] = $this->asText($fieldset->div->div[1]);
-        $results['name'] = $this->asText($fieldset->legend);
+        $results['summary'] = $this->asText($details->div->div[1]);
+        $results['name'] = $this->asText($details->summary);
 
         $results['assertions'] = array();
-        $tbody = $fieldset->div->table->tbody;
+        $tbody = $details->div->table->tbody;
         foreach ($tbody->tr as $row) {
           $assertion = array();
           $assertion['message'] = $this->asText($row->td[0]);
@@ -300,14 +300,14 @@ function getTestResults() {
   }
 
   /**
-   * Get the fieldset containing the results for group this test is in.
+   * Get the details containing the results for group this test is in.
    */
   function getResultFieldSet() {
-    $fieldsets = $this->xpath('//fieldset');
+    $all_details = $this->xpath('//details');
     $info = $this->getInfo();
-    foreach ($fieldsets as $fieldset) {
-      if ($this->asText($fieldset->legend) == $info['name']) {
-        return $fieldset;
+    foreach ($all_details as $details) {
+      if ($this->asText($details->summary) == $info['name']) {
+        return $details;
       }
     }
     return FALSE;
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index c0a59e0b00f1..001e52134476 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -1387,7 +1387,7 @@ protected function drupalPostAJAX($path, $edit, $triggering_element, $ajax_path
             if ($wrapperNode) {
               // ajax.js adds an enclosing DIV to work around a Safari bug.
               $newDom = new DOMDocument();
-              $newDom->loadHTML('<div>' . $command['data'] . '</div>');
+              @$newDom->loadHTML('<div>' . $command['data'] . '</div>');
               $newNode = $dom->importNode($newDom->documentElement->firstChild->firstChild, TRUE);
               $method = isset($command['method']) ? $command['method'] : $ajax_settings['method'];
               // The "method" is a jQuery DOM manipulation function. Emulate
diff --git a/core/modules/simpletest/simpletest.pages.inc b/core/modules/simpletest/simpletest.pages.inc
index ac2950aa8f55..d5e8c5f88327 100644
--- a/core/modules/simpletest/simpletest.pages.inc
+++ b/core/modules/simpletest/simpletest.pages.inc
@@ -10,7 +10,7 @@
  */
 function simpletest_test_form($form) {
   $form['tests'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Tests'),
     '#description' => t('Select the test(s) or test group(s) you would like to run, and click <em>Run tests</em>.'),
   );
@@ -41,7 +41,7 @@ function simpletest_test_form($form) {
     '#value' => t('Run tests'),
   );
   $form['clean'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#collapsible' => FALSE,
     '#collapsed' => FALSE,
     '#title' => t('Clean test environment'),
@@ -219,9 +219,9 @@ function simpletest_result_form($form, &$form_state, $test_id) {
     'fail' => array(),
   );
 
-  // Summary result fieldset.
+  // Summary result widget.
   $form['result'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Results'),
   );
   $form['result']['summary'] = $summary = array(
@@ -238,10 +238,10 @@ function simpletest_result_form($form, &$form_state, $test_id) {
   $header = array(t('Message'), t('Group'), t('Filename'), t('Line'), t('Function'), array('colspan' => 2, 'data' => t('Status')));
   $form['result']['results'] = array();
   foreach ($results as $group => $assertions) {
-    // Create group fieldset with summary information.
+    // Create group details with summary information.
     $info = call_user_func(array($group, 'getInfo'));
     $form['result']['results'][$group] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => $info['name'],
       '#description' => $info['description'],
       '#collapsible' => TRUE,
@@ -289,7 +289,7 @@ function simpletest_result_form($form, &$form_state, $test_id) {
   // Actions.
   $form['#action'] = url('admin/config/development/testing/results/re-run');
   $form['action'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Actions'),
     '#attributes' => array('class' => array('container-inline')),
     '#weight' => -11,
@@ -437,7 +437,7 @@ function simpletest_result_status_image($status) {
 function simpletest_settings_form($form, &$form_state) {
   $config = config('simpletest.settings');
   $form['general'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('General'),
   );
   $form['general']['simpletest_clear_results'] = array(
@@ -454,7 +454,7 @@ function simpletest_settings_form($form, &$form_state) {
   );
 
   $form['httpauth'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('HTTP authentication'),
     '#description' => t('HTTP auth settings to be used by the SimpleTest browser during testing. Useful when the site requires basic HTTP authentication.'),
     '#collapsible' => TRUE,
diff --git a/core/modules/statistics/statistics.admin.inc b/core/modules/statistics/statistics.admin.inc
index bec1eb51f831..5e0e25696ecf 100644
--- a/core/modules/statistics/statistics.admin.inc
+++ b/core/modules/statistics/statistics.admin.inc
@@ -331,7 +331,7 @@ function statistics_settings_form($form, &$form_state) {
   $config = config('statistics.settings');
   // Access log settings.
   $form['access'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Access log settings'),
   );
   $form['access']['statistics_enable_access_log'] = array(
@@ -350,7 +350,7 @@ function statistics_settings_form($form, &$form_state) {
 
   // Content counter settings.
   $form['content'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Content viewing counter settings'),
   );
   $form['content']['statistics_count_content_views'] = array(
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/ArrayUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/ArrayUnitTest.php
index 48425e22bf63..ede0b0b47f07 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/ArrayUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/ArrayUnitTest.php
@@ -36,12 +36,12 @@ function setUp() {
     parent::setUp();
 
     // Create a form structure with a nested element.
-    $this->form['fieldset']['element'] = array(
+    $this->form['details']['element'] = array(
      '#value' => 'Nested element',
     );
 
     // Set up parent array.
-    $this->parents = array('fieldset', 'element');
+    $this->parents = array('details', 'element');
   }
 
   /**
@@ -57,7 +57,7 @@ function testGet() {
     $value['#value'] = 'New value';
     $value = drupal_array_get_nested_value($this->form, $this->parents);
     $this->assertEqual($value['#value'], 'New value', 'Nested element value was changed by reference.');
-    $this->assertEqual($this->form['fieldset']['element']['#value'], 'New value', 'Nested element value was changed by reference.');
+    $this->assertEqual($this->form['details']['element']['#value'], 'New value', 'Nested element value was changed by reference.');
 
     // Verify that an existing key is reported back.
     $key_exists = NULL;
@@ -83,8 +83,8 @@ function testSet() {
 
     // Verify setting the value of a nested element.
     drupal_array_set_nested_value($this->form, $this->parents, $new_value);
-    $this->assertEqual($this->form['fieldset']['element']['#value'], 'New value', 'Changed nested element value found.');
-    $this->assertIdentical($this->form['fieldset']['element']['#required'], TRUE, 'New nested element value found.');
+    $this->assertEqual($this->form['details']['element']['#value'], 'New value', 'Changed nested element value found.');
+    $this->assertIdentical($this->form['details']['element']['#required'], TRUE, 'New nested element value found.');
   }
 
   /**
@@ -97,13 +97,13 @@ function testUnset() {
     $parents = $this->parents;
     $parents[] = 'foo';
     drupal_array_unset_nested_value($this->form, $parents, $key_existed);
-    $this->assertTrue(isset($this->form['fieldset']['element']['#value']), 'Outermost nested element key still exists.');
+    $this->assertTrue(isset($this->form['details']['element']['#value']), 'Outermost nested element key still exists.');
     $this->assertIdentical($key_existed, FALSE, 'Non-existing key not found.');
 
     // Verify unsetting a nested element.
     $key_existed = NULL;
     drupal_array_unset_nested_value($this->form, $this->parents, $key_existed);
-    $this->assertFalse(isset($this->form['fieldset']['element']), 'Removed nested element not found.');
+    $this->assertFalse(isset($this->form['details']['element']), 'Removed nested element not found.');
     $this->assertIdentical($key_existed, TRUE, 'Existing key was found.');
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/RenderTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/RenderTest.php
index adc35ba0bf78..485dc50b1f39 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/RenderTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/RenderTest.php
@@ -94,7 +94,7 @@ function testDrupalRenderChildrenAttached() {
     $child_js = drupal_get_path('module', 'forum') . '/forum.js';
     $subchild_js = drupal_get_path('module', 'book') . '/book.js';
     $element = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#cache' => array(
         'keys' => array('simpletest', 'drupal_render', 'children_attached'),
       ),
@@ -102,7 +102,7 @@ function testDrupalRenderChildrenAttached() {
       '#title' => 'Parent',
     );
     $element['child'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#attached' => array('js' => array($child_js)),
       '#title' => 'Child',
     );
@@ -240,19 +240,19 @@ function testDrupalRenderFormElements() {
     ));
 
     $element = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => $this->randomName(),
     );
-    $this->assertRenderedElement($element, '//fieldset/legend[contains(., :title)]', array(
+    $this->assertRenderedElement($element, '//details/summary[contains(., :title)]', array(
       ':title' => $element['#title'],
     ));
 
     $element = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => $this->randomName(),
       '#collapsible' => TRUE,
     );
-    $this->assertRenderedElement($element, '//fieldset[contains(@class, :class)]', array(
+    $this->assertRenderedElement($element, '//details[contains(@class, :class)]', array(
       ':class' => 'collapsible',
     ));
 
@@ -261,7 +261,7 @@ function testDrupalRenderFormElements() {
       '#title' => $this->randomName(),
       '#markup' => $this->randomName(),
     );
-    $this->assertRenderedElement($element, '//fieldset/div/div[contains(@class, :class) and contains(., :markup)]', array(
+    $this->assertRenderedElement($element, '//details/div/div[contains(@class, :class) and contains(., :markup)]', array(
       ':class' => 'form-type-item',
       ':markup' => $element['item']['#markup'],
     ));
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 8c59d8280f98..7de746f13461 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -248,7 +248,7 @@ function system_themes_page() {
 function system_themes_admin_form($form, &$form_state, $theme_options) {
   // Administration theme settings.
   $form['admin_theme'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Administration theme'),
   );
   $form['admin_theme']['admin_theme'] = array(
@@ -419,7 +419,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
   }
 
   $form['theme_settings'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Toggle display'),
     '#description' => t('Enable or disable the display of certain page elements.'),
   );
@@ -434,7 +434,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
   }
 
   if (!element_children($form['theme_settings'])) {
-    // If there is no element in the theme settings fieldset then do not show
+    // If there is no element in the theme settings details then do not show
     // it -- but keep it in the form if another module wants to alter.
     $form['theme_settings']['#access'] = FALSE;
   }
@@ -442,7 +442,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
   // Logo settings, only available when file.module is enabled.
   if ((!$key) || in_array('logo', $features) && module_exists('file')) {
     $form['logo'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Logo image settings'),
       '#attributes' => array('class' => array('theme-settings-bottom')),
     );
@@ -476,7 +476,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
 
   if ((!$key) || in_array('favicon', $features) && module_exists('file')) {
     $form['favicon'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Shortcut icon settings'),
       '#description' => t("Your shortcut icon, or 'favicon', is displayed in the address bar and bookmarks of most browsers."),
     );
@@ -545,7 +545,7 @@ function system_theme_settings($form, &$form_state, $key = '') {
     $function = $themes[$key]->prefix . '_engine_settings';
     if (function_exists($function)) {
       $form['engine_specific'] = array(
-        '#type' => 'fieldset',
+        '#type' => 'details',
         '#title' => t('Theme-engine-specific settings'),
         '#description' => t('These settings only exist for the themes based on the %engine theme engine.', array('%engine' => $themes[$key]->prefix)),
       );
@@ -911,24 +911,24 @@ function system_modules($form, $form_state = array()) {
     $form['modules'][$module->info['package']][$filename] = _system_modules_build_row($module->info, $extra);
   }
 
-  // Add basic information to the fieldsets.
+  // Add basic information to the details.
   foreach (element_children($form['modules']) as $package) {
     $form['modules'][$package] += array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t($package),
       '#collapsible' => TRUE,
-      '#theme' => 'system_modules_fieldset',
+      '#theme' => 'system_modules_details',
       '#header' => array(
         array('data' => t('<span class="element-invisible">Enabled</span>'), 'class' => array('checkbox')),
         array('data' => t('Name'), 'class' => array('name')),
         array('data' => t('Description'), 'class' => array('description', RESPONSIVE_PRIORITY_LOW)),
       ),
-      // Ensure that the "Core" package fieldset comes first.
+      // Ensure that the "Core" package comes first.
       '#weight' => $package == 'Core' ? -10 : NULL,
     );
   }
 
-  // Lastly, sort all fieldsets by title.
+  // Lastly, sort all packages by title.
   uasort($form['modules'], 'element_sort_by_title');
 
   $form['#attached']['library'][] = array('system', 'drupal.system.modules');
@@ -1384,7 +1384,7 @@ function system_site_information_settings($form, &$form_state) {
   }
 
   $form['site_information'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Site details'),
   );
   $form['site_information']['site_name'] = array(
@@ -1407,7 +1407,7 @@ function system_site_information_settings($form, &$form_state) {
     '#required' => TRUE,
   );
   $form['front_page'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Front page'),
   );
   $front_page = $site_config->get('page.front') != 'user' ? drupal_container()->get('path.alias_manager')->getPathAlias($site_config->get('page.front')) : '';
@@ -1420,7 +1420,7 @@ function system_site_information_settings($form, &$form_state) {
     '#field_prefix' => url(NULL, array('absolute' => TRUE)),
   );
   $form['error_page'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Error pages'),
   );
   $form['error_page']['site_403'] = array(
@@ -1518,7 +1518,7 @@ function system_cron_settings($form, &$form_state) {
   );
 
   $form['cron'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
   );
   $form['cron']['cron_safe_threshold'] = array(
     '#type' => 'select',
@@ -1603,7 +1603,7 @@ function system_performance_settings($form, &$form_state) {
   $config = config('system.performance');
 
   $form['clear_cache'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Clear cache'),
   );
 
@@ -1614,7 +1614,7 @@ function system_performance_settings($form, &$form_state) {
   );
 
   $form['caching'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Caching'),
   );
 
@@ -1644,7 +1644,7 @@ function system_performance_settings($form, &$form_state) {
   }
 
   $form['bandwidth_optimization'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Bandwidth optimization'),
     '#description' => t('External resources can be optimized automatically, which can reduce both the size and number of requests made to your website.') . $disabled_message,
   );
@@ -1870,7 +1870,7 @@ function system_regional_settings() {
   $zones = system_time_zones();
 
   $form['locale'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Locale'),
   );
 
@@ -1891,7 +1891,7 @@ function system_regional_settings() {
   );
 
   $form['timezone'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Time zones'),
   );
 
@@ -2493,12 +2493,12 @@ function theme_status_report($variables) {
  *
  * @ingroup themeable
  */
-function theme_system_modules_fieldset($variables) {
+function theme_system_modules_details($variables) {
   $form = $variables['form'];
 
   // Individual table headers.
   $rows = array();
-  // Iterate through all the modules, which are children of this fieldset.
+  // Iterate through all the modules, which are children of this element.
   foreach (element_children($form) as $key) {
     // Stick the key into $module for easier access.
     $module = $form[$key];
diff --git a/core/modules/system/system.base.css b/core/modules/system/system.base.css
index c50b0853fc43..f336ebd65f82 100644
--- a/core/modules/system/system.base.css
+++ b/core/modules/system/system.base.css
@@ -38,25 +38,13 @@
 }
 
 /**
- * Collapsible fieldsets.
+ * Collapsible details.
  *
  * @see collapse.js
  */
-.js fieldset.collapsed {
-  border-bottom-width: 0;
-  border-left-width: 0;
-  border-right-width: 0;
-  height: 1em;
-}
-.js fieldset.collapsed .fieldset-wrapper {
+.js details:not([open]) .details-wrapper {
   display: none;
 }
-fieldset.collapsible {
-  position: relative;
-}
-fieldset.collapsible .fieldset-legend {
-  display: block;
-}
 
 /**
  * Resizable textareas.
@@ -192,8 +180,8 @@ tr .ajax-progress-throbber .throbber {
 .container-inline label {
   display: inline;
 }
-/* Fieldset contents always need to be rendered as block. */
-.container-inline .fieldset-wrapper {
+/* Details contents always need to be rendered as block. */
+.container-inline .details-wrapper {
   display: block;
 }
 
@@ -216,7 +204,7 @@ tr .ajax-progress-throbber .throbber {
  * Hide elements from all users.
  *
  * Used for elements which should not be immediately displayed to any user. An
- * example would be a collapsible fieldset that will be expanded with a click
+ * example would be collapsible details that will be expanded with a click
  * from a user. The effect of this class can be toggled with the jQuery show()
  * and hide() functions.
  */
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 28260069edfe..e837fe9e13b4 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -150,7 +150,7 @@ function system_theme() {
     'confirm_form' => array(
       'render element' => 'form',
     ),
-    'system_modules_fieldset' => array(
+    'system_modules_details' => array(
       'render element' => 'form',
       'file' => 'system.admin.inc',
     ),
@@ -521,12 +521,17 @@ function system_element_info() {
     '#pre_render' => array('drupal_pre_render_link'),
   );
   $types['fieldset'] = array(
+    '#value' => NULL,
+    '#process' => array('ajax_process_form'),
+    '#theme_wrappers' => array('fieldset'),
+  );
+  $types['details'] = array(
     '#collapsible' => FALSE,
     '#collapsed' => FALSE,
     '#value' => NULL,
-    '#process' => array('form_process_fieldset', 'ajax_process_form'),
-    '#pre_render' => array('form_pre_render_fieldset'),
-    '#theme_wrappers' => array('fieldset'),
+    '#process' => array('form_process_details', 'ajax_process_form'),
+    '#pre_render' => array('form_pre_render_details'),
+    '#theme_wrappers' => array('details'),
   );
   $types['vertical_tabs'] = array(
     '#theme_wrappers' => array('vertical_tabs'),
@@ -1231,9 +1236,9 @@ function system_library_info() {
     ),
   );
 
-  // Drupal's collapsible fieldset.
+  // Drupal's collapsible details.
   $libraries['drupal.collapse'] = array(
-    'title' => 'Drupal collapsible fieldset',
+    'title' => 'Drupal collapsible details',
     'version' => VERSION,
     'js' => array(
       'core/misc/collapse.js' => array('group' => JS_DEFAULT),
@@ -2500,7 +2505,7 @@ function system_user_timezone(&$form, &$form_state) {
 
   $account = $form_state['controller']->getEntity($form_state);
   $form['timezone'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Locale settings'),
     '#weight' => 6,
     '#collapsible' => TRUE,
diff --git a/core/modules/system/system.theme-rtl.css b/core/modules/system/system.theme-rtl.css
index 27b8ce715fba..0b860b4f3a50 100644
--- a/core/modules/system/system.theme-rtl.css
+++ b/core/modules/system/system.theme-rtl.css
@@ -42,16 +42,19 @@ caption {
 }
 
 /**
- * Collapsible fieldsets.
+ * Collapsible details.
  */
-.js fieldset.collapsible > legend .fieldset-legend {
-  background-position: 98% 75%;
-  padding-left: 0;
-  padding-right: 15px;
+.collapse-processed > summary:before {
+  background-position: 100% 100%;
+  float: right;
 }
-.js fieldset.collapsed > legend .fieldset-legend {
-  background-image: url(../../misc/menu-collapsed-rtl.png);
-  background-position: 98% 50%;
+.collapse-processed:not([open]) > summary:before {
+  background-position: 75% 35%;
+  -moz-transform: rotate(90deg);
+  -ms-transform: rotate(90deg);
+  -o-transform: rotate(90deg);
+  -webkit-transform: rotate(90deg);
+  transform: rotate(90deg);
 }
 
 /**
diff --git a/core/modules/system/system.theme.css b/core/modules/system/system.theme.css
index 4d49d84c596b..770fa1ab82e8 100644
--- a/core/modules/system/system.theme.css
+++ b/core/modules/system/system.theme.css
@@ -8,7 +8,8 @@
  * HTML elements.
  */
 fieldset {
-  margin-bottom: 1em;
+  border: 1px solid #ccc;
+  margin: 1em 0;
   padding: 0.5em;
 }
 form {
@@ -183,22 +184,43 @@ abbr.form-required, abbr.tabledrag-changed, abbr.ajax-changed {
 }
 
 /**
- * Collapsible fieldsets.
+ * Collapsible details.
  *
  * @see collapse.js
+ * @thanks http://nicolasgallagher.com/css-background-image-hacks/
  */
-.js fieldset.collapsible > legend .fieldset-legend a {
-  background: url(../../misc/menu-expanded.png) 5px 65% no-repeat; /* LTR */
-  padding-left: 15px; /* LTR */
-}
-.js fieldset.collapsed > legend .fieldset-legend a {
-  background-image: url(../../misc/menu-collapsed.png); /* LTR */
-  background-position: 5px 50%; /* LTR */
+details {
+  border: 1px solid #ccc;
+  margin-top: 1em;
+  margin-bottom: 1em;
 }
-.fieldset-legend span.summary {
-  color: #999;
-  font-size: 0.9em;
-  margin-left: 0.5em;
+details > .details-wrapper {
+  padding: 0.5em 1.5em;
+}
+/* @todo Regression: The summary of uncollapsible details are no longer
+     vertically aligned with the .details-wrapper in browsers without native
+     details support. */
+summary {
+  padding: 0.2em 0.5em;
+}
+.collapse-processed > summary {
+  padding-left: 0.5em;
+  padding-right: 0.5em;
+}
+.collapse-processed > summary:before {
+  background: url(../../misc/menu-expanded.png) 0px 100% no-repeat; /* LTR */
+  content: "";
+  float: left;
+  height: 1em;
+  width: 1em;
+}
+.collapse-processed:not([open]) > summary:before {
+  background-position: 25% 35%; /* LTR */
+  -moz-transform: rotate(-90deg);
+  -ms-transform: rotate(-90deg);
+  -o-transform: rotate(-90deg);
+  -webkit-transform: rotate(-90deg);
+  transform: rotate(-90deg);
 }
 
 /**
diff --git a/core/modules/system/tests/modules/design_test/design_test.info b/core/modules/system/tests/modules/design_test/design_test.info
new file mode 100644
index 000000000000..ff7159ccc64e
--- /dev/null
+++ b/core/modules/system/tests/modules/design_test/design_test.info
@@ -0,0 +1,6 @@
+name = Design test
+description = Support module for design, markup, JavaScript, and CSS testing.
+package = Testing
+version = VERSION
+core = 8.x
+;hidden = TRUE
diff --git a/core/modules/system/tests/modules/design_test/design_test.module b/core/modules/system/tests/modules/design_test/design_test.module
new file mode 100644
index 000000000000..b8a1a80c7781
--- /dev/null
+++ b/core/modules/system/tests/modules/design_test/design_test.module
@@ -0,0 +1,169 @@
+<?php
+
+/**
+ * @file
+ * Support module for design, markup, JavaScript, and CSS testing.
+ */
+
+/**
+ * Implements hook_menu().
+ *
+ * This implementation turns every subdirectory of this module into a category
+ * that is exposed as a menu link. Each subdirectory contains include files that
+ * consist of a callback function that maps to the semantics of the category.
+ * The following categories are supported:
+ * - form: Used for Form API element tests.
+ * - page: Used for theme function tests.
+ *
+ * For example, given an include file:
+ * @code
+ * ./page/list-operations.inc
+ * @endcode
+ * A menu router item with the path 'design_test/page/list-operations' will be
+ * auto-generated. Upon access, the function design_test_page_list_operations()
+ * will be called.
+ *
+ * The 'form' category behaves identically; e.g., for an include file
+ * './form/details.inc' a menu item for the path 'design_test/form/details' is
+ * created and the form constructor function design_test_form_details() will be
+ * called.
+ *
+ * Each resulting test page is enhanced with local actions that allow to quickly
+ * switch between enabled themes for verifying the expected output.
+ */
+function design_test_menu() {
+  // Turn each include file in the module directory into a local task.
+  $categories = array();
+  $module_path = drupal_get_path('module', 'design_test');
+  $tests = file_scan_directory($module_path, '/\.inc$/', array('key' => 'name', 'recurse' => TRUE));
+  foreach ($tests as $name => $file) {
+    // Build include file path and category.
+    $filepath = strtr($file->uri, array($module_path . '/' => ''));
+    list($category) = explode('/', $filepath, 2);
+    $categories[$category] = $category;
+
+    // Build router item path.
+    $path = preg_replace('@[^a-zA-Z0-9-]@', '-', $name);
+    // Build page callback function name.
+    $callback = "design_test_{$category}_" . strtr($path, '-', '_');
+
+    // Build router item callback.
+    if ($category == 'form') {
+      $page_callback = 'drupal_get_form';
+    }
+    else {
+      $page_callback = $callback;
+    }
+
+    $items["design_test/{$category}/{$path}"] = array(
+      'title' => drupal_ucfirst($name),
+      'theme callback' => 'design_test_menu_theme_callback',
+      'page callback' => $page_callback,
+      'page arguments' => array($callback),
+      'file' => $filepath,
+      'access callback' => TRUE,
+      'type' => MENU_LOCAL_TASK | MENU_VISIBLE_IN_TREE,
+    );
+  }
+
+  $items['design_test'] = array(
+    'title' => 'Design test',
+    'page callback' => 'design_test_category_page',
+    'page arguments' => array(1),
+    'access callback' => TRUE,
+  );
+  $items['design_test/list'] = array(
+    'title' => 'List',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+  // Lastly, add the category containers.
+  foreach ($categories as $category) {
+    $items["design_test/{$category}"] = array(
+      'title' => drupal_ucfirst($category),
+      'page callback' => 'design_test_category_page',
+      'page arguments' => array(1),
+      'access callback' => TRUE,
+      'type' => MENU_LOCAL_TASK | MENU_VISIBLE_IN_TREE,
+    );
+  }
+
+  return $items;
+}
+
+/**
+ * Implements hook_menu_local_tasks_alter().
+ */
+function design_test_menu_local_tasks_alter(&$data, $router_item, $root_path) {
+  if ($router_item['number_parts'] > 2 && strpos($root_path, 'design_test/') === 0) {
+    $actions = &$data['actions']['output'];
+    // Determine the currently selected theme, if any.
+    $selected_theme = drupal_container()->get('request')->query->get('theme');
+    $default_theme = variable_get('theme_default', 'stark');
+
+    // Expand all enabled themes into action links.
+    $themes = list_themes();
+    foreach ($themes as $name => $theme) {
+      $action = array(
+        '#theme' => 'menu_local_action',
+        '#link' => array(
+          'title' => $theme->info['name'],
+          'href' => $router_item['href'],
+          'localized_options' => array('html' => FALSE),
+        ),
+        '#active' => $selected_theme == $name,
+      );
+      // Only add the theme-switcher query parameter for all non-default themes.
+      if ($name != $default_theme) {
+        $action['#link']['localized_options']['query']['theme'] = $name;
+      }
+      $actions[] = $action;
+    }
+    if ($themes > 1) {
+      $data['actions']['count']++;
+    }
+  }
+}
+
+/**
+ * Menu theme callback for design_test pages.
+ *
+ * Returns whichever theme name that has been passed via the 'theme' request
+ * query parameter. The returned value is validated by the menu system already.
+ */
+function design_test_menu_theme_callback() {
+  return drupal_container()->get('request')->query->get('theme');
+}
+
+/**
+ * Menu page callback for a category listing page.
+ *
+ * This is a specialized version of system_admin_menu_block_page(), which
+ * retrieves all direct child menu links of the current page, regardless of
+ * their type, skips default local tasks, and outputs them as a simple menu
+ * tree as the main page content.
+ *
+ * @param string $category
+ *   The design test category being currently accessed. Maps to the subdirectory
+ *   names of this module.
+ *
+ * @return array
+ *   A render array containing a menu link tree.
+ */
+function design_test_category_page($category) {
+  $link = menu_link_get_preferred();
+  $tree = menu_build_tree($link['menu_name'], array(
+    'expanded' => array($link['mlid']),
+    'min_depth' => $link['depth'] + 1,
+    'max_depth' => $link['depth'] + 2,
+  ));
+  // Local tasks are hidden = -1, so normally not rendered in menu trees.
+  foreach ($tree as &$data) {
+    // Exclude default local tasks.
+    if (!($data['link']['type'] & MENU_LINKS_TO_PARENT)) {
+      $data['link']['hidden'] = 0;
+    }
+  }
+  $build = menu_tree_output($tree);
+  return $build;
+}
diff --git a/core/modules/system/tests/modules/design_test/form/details.inc b/core/modules/system/tests/modules/design_test/form/details.inc
new file mode 100644
index 000000000000..186945ff7051
--- /dev/null
+++ b/core/modules/system/tests/modules/design_test/form/details.inc
@@ -0,0 +1,178 @@
+<?php
+
+/**
+ * @file
+ * Details design test.
+ */
+
+/**
+ * Form constructor for testing theme_details().
+ */
+function design_test_form_details($form, &$form_state) {
+  $form['collapsible'] = array(
+    '#type' => 'details',
+    '#title' => 'Collapsible details',
+    '#description' => 'Details description',
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+    '#states' => array(
+      'collapsed' => array(
+        ':input[name="states-trigger"]' => array('checked' => TRUE),
+      ),
+    ),
+  );
+
+  $form['collapsed'] = array(
+    '#type' => 'details',
+    '#title' => 'Collapsed details',
+    '#description' => 'Details description',
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $form['collapsed']['textfield'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Textfield',
+    '#default_value' => '',
+    '#description' => 'Textfield description',
+    '#required' => TRUE,
+  );
+  $form['collapsed']['textarea'] = array(
+    '#type' => 'textarea',
+    '#title' => 'Textarea',
+    '#default_value' => '',
+    '#description' => 'Textarea description',
+    '#required' => TRUE,
+  );
+
+  $form['collapsed2'] = array(
+    '#type' => 'details',
+    '#title' => 'Details',
+    '#description' => 'Details description',
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $form['collapsed2']['collapsible'] = array(
+    '#type' => 'details',
+    '#title' => 'Collapsible details',
+    '#description' => 'Details description',
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+  $form['collapsed2']['collapsed'] = array(
+    '#type' => 'details',
+    '#title' => 'Collapsed details',
+    '#description' => 'Details description',
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $form['collapsed2']['regular'] = array(
+    '#type' => 'details',
+    '#title' => 'Details',
+    '#description' => 'Details description',
+    '#collapsible' => FALSE,
+  );
+
+  $form['regular'] = array(
+    '#type' => 'details',
+    '#title' => 'Details',
+    '#description' => 'Details description',
+    '#collapsible' => FALSE,
+  );
+
+  #$form['#attributes'] = array('class' => array('search-form'));
+  $form['basic'] = array(
+    '#type' => 'details',
+    '#title' => 'Filter aliases',
+    '#attributes' => array('class' => array('container-inline')),
+  );
+  $form['basic']['filter'] = array(
+    '#type' => 'textfield',
+    '#title' => '',
+    '#default_value' => '',
+    '#maxlength' => 128,
+    '#size' => 25,
+  );
+  $form['basic']['actions'] = array(
+    '#type' => 'actions',
+  );
+  $form['basic']['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => 'Filter',
+  );
+  $form['basic']['actions']['reset'] = array(
+    '#type' => 'submit',
+    '#value' => 'Reset',
+  );
+
+  $form['body'] = array(
+    '#type' => 'text_format',
+    '#title' => 'Body',
+  );
+
+  // Vertical tabs.
+  // Replicate the entire form; some more black magic.
+  $subform = array_diff_key($form, array('group' => 0, 'tabs' => 0));
+
+  $form['group'] = array(
+    '#type' => 'vertical_tabs',
+  );
+  $form['tabs'][0] = array(
+    '#type' => 'details',
+    '#title' => 'Vertical tab 1',
+    '#description' => 'Description',
+    '#group' => 'group',
+  );
+  $form['tabs'][0] += $subform;
+
+  $form['tabs'][1] = array(
+    '#type' => 'details',
+    '#title' => 'Vertical tab 2',
+    '#description' => '<p>Description</p><p>Description</p>',
+    '#group' => 'group',
+  );
+  $form['tabs'][1] += $subform;
+
+  // In case you didn't know, vertical tabs are supported recursively.
+  $form['tabs'][0]['subgroup'] = array(
+    '#type' => 'vertical_tabs',
+  );
+
+  $form['subtabs'][0] = array(
+    '#type' => 'details',
+    '#title' => 'Vertical tab 1',
+    '#description' => 'Description',
+    '#group' => 'subgroup',
+  );
+  $form['subtabs'][0] += $subform;
+
+  $form['subtabs'][1] = array(
+    '#type' => 'details',
+    '#title' => 'Vertical tab 2',
+    '#description' => '<p>Description</p><p>Description</p>',
+    '#group' => 'subgroup',
+  );
+  $form['subtabs'][1] += $subform;
+
+
+  // #states supports:
+  // - a 'collapsed' state trigger
+  // - a 'collapsed' remote condition
+  $form['states-trigger'] = array(
+    '#type' => 'checkbox',
+    '#title' => 'Collapse first details',
+    '#weight' => -100,
+  );
+  $form['states-condition'] = array(
+    '#type' => 'checkbox',
+    '#title' => 'Required if second details are collapsed.',
+    '#states' => array(
+      'required' => array(
+        'details#edit-collapsed' => array('collapsed' => TRUE),
+      ),
+    ),
+    '#weight' => -100,
+  );
+
+  return $form;
+}
+
diff --git a/core/modules/system/tests/modules/design_test/form/fieldset.inc b/core/modules/system/tests/modules/design_test/form/fieldset.inc
new file mode 100644
index 000000000000..4ab07fd01286
--- /dev/null
+++ b/core/modules/system/tests/modules/design_test/form/fieldset.inc
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Fieldset design test.
+ */
+
+/**
+ * Form constructor for testing theme_fieldset().
+ */
+function design_test_form_fieldset($form, &$form_state) {
+  $form['regular'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Fieldset',
+    '#description' => 'Fieldset description',
+  );
+
+  $form['collapsible'] = array(
+    '#type' => 'details',
+    '#title' => 'Collapsible details',
+    '#description' => 'Details description',
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+  $form['collapsible']['fieldset'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Fieldset title',
+    '#description' => 'Fieldset description',
+  );
+  $form['collapsible']['fieldset']['textfield'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Textfield',
+    '#description' => 'Textfield description',
+    '#required' => TRUE,
+  );
+  $form['collapsible']['fieldset']['textarea'] = array(
+    '#type' => 'textarea',
+    '#title' => 'Textarea',
+    '#description' => 'Textarea description',
+  );
+
+  $form['collapsed'] = $form['collapsible'];
+  $form['collapsed']['#title'] = 'Collapsed details';
+  $form['collapsed']['#collapsed'] = TRUE;
+
+  $form['uncollapsible'] = $form['collapsible'];
+  $form['uncollapsible']['#title'] = 'Uncollapsible details';
+  $form['uncollapsible']['#collapsible'] = FALSE;
+
+  $form['nested'] = $form['regular'];
+  $form['nested']['#title'] = 'Parent fieldset';
+  $form['nested']['nested'] = $form['nested'];
+  $form['nested']['nested']['#title'] = 'Nested fieldset';
+
+  // Vertical tabs.
+  // Replicate the entire form; some more black magic.
+  $subform = array_diff_key($form, array('group' => 0, 'tabs' => 0));
+
+  $form['group'] = array(
+    '#type' => 'vertical_tabs',
+  );
+  $form['tabs'][0] = array(
+    '#type' => 'details',
+    '#title' => 'Vertical tab 1',
+    '#description' => 'Description',
+    '#group' => 'group',
+  );
+  $form['tabs'][0] += $subform;
+
+  $form['tabs'][1] = array(
+    '#type' => 'details',
+    '#title' => 'Vertical tab 2',
+    '#description' => '<p>Description</p><p>Description</p>',
+    '#group' => 'group',
+  );
+  $form['tabs'][1] += $subform;
+
+  // In case you didn't know, vertical tabs are supported recursively.
+  $form['tabs'][0]['subgroup'] = array(
+    '#type' => 'vertical_tabs',
+  );
+
+  $form['subtabs'][0] = array(
+    '#type' => 'details',
+    '#title' => 'Vertical tab 1',
+    '#description' => 'Description',
+    '#group' => 'subgroup',
+  );
+  $form['subtabs'][0] += $subform;
+
+  $form['subtabs'][1] = array(
+    '#type' => 'details',
+    '#title' => 'Vertical tab 2',
+    '#description' => '<p>Description</p><p>Description</p>',
+    '#group' => 'subgroup',
+  );
+  $form['subtabs'][1] += $subform;
+
+  return $form;
+}
+
diff --git a/core/modules/system/tests/modules/design_test/page/list-operations.inc b/core/modules/system/tests/modules/design_test/page/list-operations.inc
new file mode 100644
index 000000000000..7675e493a47a
--- /dev/null
+++ b/core/modules/system/tests/modules/design_test/page/list-operations.inc
@@ -0,0 +1,84 @@
+<?php
+
+/**
+ * @file
+ * Tests Operations.
+ */
+
+/**
+ * Page callback for manual testing of operation links.
+ */
+function design_test_page_list_operations() {
+  $build = array(
+    '#theme' => 'table',
+    '#header' => array('Label', 'Created', 'Operations'),
+    '#rows' => array(),
+  );
+  // Add an item with a very long label, using common operations.
+  $build['#rows']['long']['label'] = l('An item with a very insanely long label, which offers quite a couple of common operations', 'item/long');
+  $build['#rows']['long']['created'] = format_interval(3200);
+  $build['#rows']['long']['operations'] = array(
+    'data' => array(
+      '#type' => 'operations',
+      '#subtype' => 'node',
+      '#links' => array(
+        'edit' => array(
+          'title' => 'edit',
+          'href' => 'item/long/edit',
+        ),
+        'disable' => array(
+          'title' => 'disable',
+          'href' => 'item/long/disable',
+        ),
+        'clone' => array(
+          'title' => 'clone',
+          'href' => 'item/long/clone',
+        ),
+        'delete' => array(
+          'title' => 'delete',
+          'href' => 'item/long/delete',
+        ),
+      ),
+    ),
+  );
+
+  // Add another item, using common operations.
+  $build['#rows']['another']['label'] = l('Another item, using common operations', 'item/another');
+  $build['#rows']['another']['created'] = format_interval(8600);
+  $build['#rows']['another']['operations'] = $build['#rows']['long']['operations'];
+
+  // Add an item with only one operation.
+  $build['#rows']['one']['label'] = l('An item with only one operation', 'item/one');
+  $build['#rows']['one']['created'] = format_interval(12400);
+  $build['#rows']['one']['operations'] = array(
+    'data' => array(
+      '#type' => 'operations',
+      '#subtype' => 'node',
+      '#links' => array(
+        'edit' => array(
+          'title' => 'edit',
+          'href' => 'item/long/edit',
+        ),
+      ),
+    ),
+  );
+
+  // Add an item that can only be viewed.
+  $build['#rows']['view']['label'] = l('An item that can only be viewed', 'item/view');
+  $build['#rows']['view']['created'] = format_interval(12400);
+  $build['#rows']['view']['operations'] = array(
+    'data' => array(
+      '#type' => 'operations',
+      '#subtype' => 'node',
+      '#links' => array(),
+    ),
+  );
+
+  // Add an item for which the default operation is denied.
+  $build['#rows']['denied']['label'] = l('An item for which the default operation is denied', 'item/denied');
+  $build['#rows']['denied']['created'] = format_interval(18600);
+  $build['#rows']['denied']['operations'] = $build['#rows']['long']['operations'];
+  unset($build['#rows']['denied']['operations']['data']['#links']['edit']);
+
+  return $build;
+}
diff --git a/core/modules/system/tests/modules/form_test/form_test.module b/core/modules/system/tests/modules/form_test/form_test.module
index b8a38675bd1b..180180985bfc 100644
--- a/core/modules/system/tests/modules/form_test/form_test.module
+++ b/core/modules/system/tests/modules/form_test/form_test.module
@@ -797,7 +797,7 @@ function _form_test_vertical_tabs_form($form, &$form_state) {
     '#type' => 'vertical_tabs',
   );
   $form['tab1'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Tab 1'),
     '#collapsible' => TRUE,
     '#group' => 'vertical_tabs',
@@ -808,7 +808,7 @@ function _form_test_vertical_tabs_form($form, &$form_state) {
     '#type' => 'textfield',
   );
   $form['tab2'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Tab 2'),
     '#collapsible' => TRUE,
     '#group' => 'vertical_tabs',
diff --git a/core/modules/system/tests/modules/theme_test/theme_test.module b/core/modules/system/tests/modules/theme_test/theme_test.module
index f231b4988584..40196d760db2 100644
--- a/core/modules/system/tests/modules/theme_test/theme_test.module
+++ b/core/modules/system/tests/modules/theme_test/theme_test.module
@@ -59,19 +59,6 @@ function theme_test_menu() {
     'access callback' => TRUE,
     'type' => MENU_CALLBACK,
   );
-
-  $items['theme-test'] = array(
-    'title' => 'Theme test',
-    'page callback' => 'system_admin_menu_block_page',
-    'access callback' => TRUE,
-    'file path' => drupal_get_path('module', 'system'),
-    'file' => 'system.admin.inc',
-  );
-  $items['theme-test/list/operations'] = array(
-    'title' => 'Operations',
-    'page callback' => '_theme_test_list_operations',
-    'access callback' => TRUE,
-  );
   return $items;
 }
 
@@ -161,80 +148,3 @@ function theme_theme_test_foo($variables) {
   return $variables['foo'];
 }
 
-/**
- * Page callback for manual testing of operation links.
- */
-function _theme_test_list_operations() {
-  $build = array(
-    '#theme' => 'table',
-    '#header' => array('Label', 'Created', 'Operations'),
-    '#rows' => array(),
-  );
-  // Add an item with a very long label, using common operations.
-  $build['#rows']['long']['label'] = l('An item with a very insanely long label, which offers quite a couple of common operations', 'item/long');
-  $build['#rows']['long']['created'] = format_interval(3200);
-  $build['#rows']['long']['operations'] = array(
-    'data' => array(
-      '#type' => 'operations',
-      '#subtype' => 'node',
-      '#links' => array(
-        'edit' => array(
-          'title' => 'edit',
-          'href' => 'item/long/edit',
-        ),
-        'disable' => array(
-          'title' => 'disable',
-          'href' => 'item/long/disable',
-        ),
-        'clone' => array(
-          'title' => 'clone',
-          'href' => 'item/long/clone',
-        ),
-        'delete' => array(
-          'title' => 'delete',
-          'href' => 'item/long/delete',
-        ),
-      ),
-    ),
-  );
-
-  // Add another item, using common operations.
-  $build['#rows']['another']['label'] = l('Another item, using common operations', 'item/another');
-  $build['#rows']['another']['created'] = format_interval(8600);
-  $build['#rows']['another']['operations'] = $build['#rows']['long']['operations'];
-
-  // Add an item with only one operation.
-  $build['#rows']['one']['label'] = l('An item with only one operation', 'item/one');
-  $build['#rows']['one']['created'] = format_interval(12400);
-  $build['#rows']['one']['operations'] = array(
-    'data' => array(
-      '#type' => 'operations',
-      '#subtype' => 'node',
-      '#links' => array(
-        'edit' => array(
-          'title' => 'edit',
-          'href' => 'item/long/edit',
-        ),
-      ),
-    ),
-  );
-
-  // Add an item that can only be viewed.
-  $build['#rows']['view']['label'] = l('An item that can only be viewed', 'item/view');
-  $build['#rows']['view']['created'] = format_interval(12400);
-  $build['#rows']['view']['operations'] = array(
-    'data' => array(
-      '#type' => 'operations',
-      '#subtype' => 'node',
-      '#links' => array(),
-    ),
-  );
-
-  // Add an item for which the default operation is denied.
-  $build['#rows']['denied']['label'] = l('An item for which the default operation is denied', 'item/denied');
-  $build['#rows']['denied']['created'] = format_interval(18600);
-  $build['#rows']['denied']['operations'] = $build['#rows']['long']['operations'];
-  unset($build['#rows']['denied']['operations']['data']['#links']['edit']);
-
-  return $build;
-}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
index f81b9e51d179..92185c6dfcc9 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
@@ -56,7 +56,7 @@ public function form(array $form, array &$form_state, EntityInterface $term) {
     );
 
     $form['relations'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Relations'),
       '#collapsible' => TRUE,
       '#collapsed' => ($vocabulary->hierarchy != TAXONOMY_HIERARCHY_MULTIPLE),
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php
index c26251e97b21..5679f85876f5 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php
@@ -58,7 +58,7 @@ public function form(array $form, array &$form_state, EntityInterface $vocabular
     );
     if (module_exists('language')) {
       $form['default_terms_language'] = array(
-        '#type' => 'fieldset',
+        '#type' => 'details',
         '#title' => t('Terms language'),
       );
       $form['default_terms_language']['default_language'] = array(
diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module
index 2fff6c190317..69d01c35b8bb 100644
--- a/core/modules/translation/translation.module
+++ b/core/modules/translation/translation.module
@@ -211,7 +211,7 @@ function translation_form_node_form_alter(&$form, &$form_state) {
       // Add translation values and workflow options.
       $form['tnid'] = array('#type' => 'value', '#value' => $node->tnid);
       $form['translation'] = array(
-        '#type' => 'fieldset',
+        '#type' => 'details',
         '#title' => t('Translation settings'),
         '#access' => translation_user_can_translate_node($node),
         '#collapsible' => TRUE,
diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php b/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php
index 26a26992b47a..b08518a3a3da 100644
--- a/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php
+++ b/core/modules/translation_entity/lib/Drupal/translation_entity/EntityTranslationController.php
@@ -146,7 +146,7 @@ public function entityFormAlter(array &$form, array &$form_state, EntityInterfac
     // translation and there are at least two translations available.
     if ($has_translations && $new_translation) {
       $form['source_langcode'] = array(
-        '#type' => 'fieldset',
+        '#type' => 'details',
         '#title' => t('Source language: @language', array('@language' => $languages[$source_langcode]->name)),
         '#collapsible' => TRUE,
         '#collapsed' => TRUE,
@@ -214,7 +214,7 @@ public function entityFormAlter(array &$form, array &$form_state, EntityInterfac
     // translation available or a new one is about to be created.
     if ($new_translation || $has_translations) {
       $form['translation'] = array(
-        '#type' => 'fieldset',
+        '#type' => 'details',
         '#title' => t('Translation'),
         '#collapsible' => TRUE,
         '#collapsed' => TRUE,
@@ -312,7 +312,7 @@ protected function addTranslatabilityClue(&$element) {
     // Elements which can have a #title attribute according to FAPI Reference.
     if (!isset($suffix)) {
       $suffix = ' <span class="translation-entity-all-languages">(' . t('all languages') . ')</span>';
-      $fapi_title_elements = array_flip(array('checkbox', 'checkboxes', 'date', 'fieldset', 'file', 'item', 'password', 'password_confirm', 'radio', 'radios', 'select', 'text_format', 'textarea', 'textfield', 'weight'));
+      $fapi_title_elements = array_flip(array('checkbox', 'checkboxes', 'date', 'details', 'fieldset', 'file', 'item', 'password', 'password_confirm', 'radio', 'radios', 'select', 'text_format', 'textarea', 'textfield', 'weight'));
     }
 
     // Update #title attribute for all elements that are allowed to have a
diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php
index 30a6740a18aa..512f703cf678 100644
--- a/core/modules/user/lib/Drupal/user/AccountFormController.php
+++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
@@ -157,7 +157,7 @@ public function form(array $form, array &$form_state, EntityInterface $account)
 
     // Signature.
     $form['signature_settings'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Signature settings'),
       '#weight' => 1,
       '#access' => (!$register && $config->get('signatures')),
@@ -179,7 +179,7 @@ public function form(array $form, array &$form_state, EntityInterface $account)
     include_once DRUPAL_ROOT . '/core/includes/language.inc';
     $interface_language_is_default = language_negotiation_method_get_first(LANGUAGE_TYPE_INTERFACE) != LANGUAGE_NEGOTIATION_SELECTED;
     $form['language'] = array(
-      '#type' => language_multilingual() ? 'fieldset' : 'container',
+      '#type' => language_multilingual() ? 'details' : 'container',
       '#title' => t('Language settings'),
       // Display language selector when either creating a user on the admin
       // interface or editing a user account.
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserLanguageTest.php b/core/modules/user/lib/Drupal/user/Tests/UserLanguageTest.php
index 7a3c7b538b10..407bd224a495 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserLanguageTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserLanguageTest.php
@@ -59,7 +59,7 @@ function testUserLanguageConfiguration() {
     $this->drupalLogin($web_user);
     $path = 'user/' . $web_user->uid . '/edit';
     $this->drupalGet($path);
-    // Ensure language settings fieldset is available.
+    // Ensure language settings widget is available.
     $this->assertText(t('Language'), 'Language selector available.');
     // Ensure custom language is present.
     $this->assertText($name, 'Language present on form.');
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php
index 73f339687152..943d185bcda5 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserRegistrationTest.php
@@ -161,10 +161,10 @@ function testRegistrationDefaultValues() {
     variable_set('configurable_timezones', 1);
     variable_set('date_default_timezone', 'Europe/Brussels');
 
-    // Check that the account information fieldset's options are not displayed
-    // is a fieldset if there is not more than one fieldset in the form.
+    // Check that the account information options are not displayed
+    // as a details element if there is not more than one details in the form.
     $this->drupalGet('user/register');
-    $this->assertNoRaw('<fieldset id="edit-account"><legend>Account information</legend>', 'Account settings fieldset was hidden.');
+    $this->assertNoRaw('<details id="edit-account"><summary>Account information</summary>');
 
     $edit = array();
     $edit['name'] = $name = $this->randomName();
diff --git a/core/modules/user/user.admin.inc b/core/modules/user/user.admin.inc
index 277164ad9440..263add549e0e 100644
--- a/core/modules/user/user.admin.inc
+++ b/core/modules/user/user.admin.inc
@@ -38,7 +38,7 @@ function user_filter_form() {
 
   $i = 0;
   $form['filters'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Show only users where'),
     '#theme' => 'exposed_filters__user',
   );
@@ -170,7 +170,7 @@ function user_admin_account() {
   $result = $query->execute();
 
   $form['options'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Update options'),
     '#attributes' => array('class' => array('container-inline')),
   );
@@ -282,7 +282,7 @@ function user_admin_settings($form, &$form_state) {
 
   // Settings for anonymous users.
   $form['anonymous_settings'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Anonymous users'),
   );
   $form['anonymous_settings']['anonymous'] = array(
@@ -295,7 +295,7 @@ function user_admin_settings($form, &$form_state) {
 
   // Administrative role option.
   $form['admin_role'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Administrator role'),
   );
 
@@ -317,7 +317,7 @@ function user_admin_settings($form, &$form_state) {
   // @todo Remove this check once language settings are generalized.
   if (module_exists('translation_entity')) {
     $form['language'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Language settings'),
       '#tree' => TRUE,
     );
@@ -327,7 +327,7 @@ function user_admin_settings($form, &$form_state) {
 
   // User registration settings.
   $form['registration_cancellation'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Registration and cancellation'),
   );
   $form['registration_cancellation']['user_register'] = array(
@@ -368,7 +368,7 @@ function user_admin_settings($form, &$form_state) {
 
   // Account settings.
   $form['personalization'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Personalization'),
   );
   $form['personalization']['user_signatures'] = array(
@@ -389,7 +389,7 @@ function user_admin_settings($form, &$form_state) {
   $email_token_help = t('Available variables are: [site:name], [site:url], [user:name], [user:mail], [site:login-url], [site:url-brief], [user:edit-url], [user:one-time-login-url], [user:cancel-url].');
 
   $form['email_admin_created'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Welcome (new user created by administrator)'),
     '#collapsible' => TRUE,
     '#collapsed' => ($config->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY),
@@ -410,7 +410,7 @@ function user_admin_settings($form, &$form_state) {
   );
 
   $form['email_pending_approval'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Welcome (awaiting approval)'),
     '#collapsible' => TRUE,
     '#collapsed' => ($config->get('register') != USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL),
@@ -431,7 +431,7 @@ function user_admin_settings($form, &$form_state) {
   );
 
   $form['email_no_approval_required'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Welcome (no approval required)'),
     '#collapsible' => TRUE,
     '#collapsed' => ($config->get('register') != USER_REGISTER_VISITORS),
@@ -452,7 +452,7 @@ function user_admin_settings($form, &$form_state) {
   );
 
   $form['email_password_reset'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Password recovery'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
@@ -474,7 +474,7 @@ function user_admin_settings($form, &$form_state) {
   );
 
   $form['email_activated'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Account activation'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
@@ -509,7 +509,7 @@ function user_admin_settings($form, &$form_state) {
   );
 
   $form['email_blocked'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Account blocked'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
@@ -544,7 +544,7 @@ function user_admin_settings($form, &$form_state) {
   );
 
   $form['email_cancel_confirm'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Account cancellation confirmation'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
@@ -565,7 +565,7 @@ function user_admin_settings($form, &$form_state) {
   );
 
   $form['email_canceled'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Account canceled'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
diff --git a/core/modules/user/user.css b/core/modules/user/user.css
index 28aa37360cb1..8513db4dfed2 100644
--- a/core/modules/user/user.css
+++ b/core/modules/user/user.css
@@ -8,7 +8,7 @@
 #permissions tr.even .form-item {
   white-space: normal;
 }
-#user-admin-settings fieldset .fieldset-description {
+#user-admin-settings .details-description {
   font-size: 0.85em;
   padding-bottom: .5em;
 }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php
index deaf56d761cf..66869d3a821d 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php
@@ -293,9 +293,9 @@ public function buildOptionsForm(&$form, &$form_state) {
     );
 
     // This form is long and messy enough that the "Administrative title" option
-    // belongs in a "more options" fieldset at the bottom of the form.
+    // belongs in "more options" details at the bottom of the form.
     $form['more'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('More'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/area/AreaPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/area/AreaPluginBase.php
index fb747ea8252d..a757bcf57302 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/area/AreaPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/area/AreaPluginBase.php
@@ -114,7 +114,7 @@ public function tokenForm(&$form, &$form_state) {
 
     if (!empty($options)) {
       $form['tokens'] = array(
-        '#type' => 'fieldset',
+        '#type' => 'details',
         '#title' => t('Replacement patterns'),
         '#collapsible' => TRUE,
         '#collapsed' => TRUE,
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/argument/ArgumentPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/argument/ArgumentPluginBase.php
index 5ec22eac82ac..04715fbd00bf 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/argument/ArgumentPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/argument/ArgumentPluginBase.php
@@ -172,10 +172,10 @@ public function buildOptionsForm(&$form, &$form_state) {
     );
 
     $form['no_argument'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => $argument_text['filter value not present'],
     );
-    // Everything in the fieldset is floated, so the last element needs to
+    // Everything in the details is floated, so the last element needs to
     // clear those floats.
     $form['no_argument']['clearfix'] = array(
       '#weight' => 1000,
@@ -189,7 +189,7 @@ public function buildOptionsForm(&$form, &$form_state) {
     );
 
     $form['exception'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Exceptions'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
@@ -236,7 +236,7 @@ public function buildOptionsForm(&$form, &$form_state) {
     $form['default_action']['#options'] = $options;
 
     $form['argument_present'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => $argument_text['filter value present'],
     );
     $form['title_enable'] = array(
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/field/FieldPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/field/FieldPluginBase.php
index 8d6fe061d043..cdff25e51d81 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/field/FieldPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/field/FieldPluginBase.php
@@ -527,7 +527,7 @@ public function buildOptionsForm(&$form, &$form_state) {
     );
 
     $form['style_settings'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Style settings'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
@@ -678,7 +678,7 @@ public function buildOptionsForm(&$form, &$form_state) {
 
     $form['alter'] = array(
       '#title' => t('Rewrite results'),
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
       '#weight' => 100,
@@ -882,7 +882,7 @@ public function buildOptionsForm(&$form, &$form_state) {
       // the parent in situations like this, so we need a second div to
       // make this work.
       $form['alter']['help'] = array(
-        '#type' => 'fieldset',
+        '#type' => 'details',
         '#title' => t('Replacement patterns'),
         '#collapsible' => TRUE,
         '#collapsed' => TRUE,
@@ -1029,7 +1029,7 @@ public function buildOptionsForm(&$form, &$form_state) {
     }
 
     $form['empty_field_behavior'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('No results behavior'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/pager/Full.php b/core/modules/views/lib/Drupal/views/Plugin/views/pager/Full.php
index f99eabe6d69a..9e34d27883e6 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/pager/Full.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/pager/Full.php
@@ -104,7 +104,7 @@ public function buildOptionsForm(&$form, &$form_state) {
     );
 
     $form['tags'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#collapsible' => FALSE,
       '#collapsed' => FALSE,
       '#tree' => TRUE,
@@ -142,7 +142,7 @@ public function buildOptionsForm(&$form, &$form_state) {
     );
 
     $form['expose'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#collapsible' => FALSE,
       '#collapsed' => FALSE,
       '#tree' => TRUE,
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/row/RssFields.php b/core/modules/views/lib/Drupal/views/Plugin/views/row/RssFields.php
index 4a7a1e4a63c0..c140305e2902 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/row/RssFields.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/row/RssFields.php
@@ -90,7 +90,7 @@ public function buildOptionsForm(&$form, &$form_state) {
       '#required' => TRUE,
     );
     $form['guid_field_options'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('GUID settings'),
       '#collapsible' => FALSE,
       '#collapsed' => FALSE,
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php
index 0e8546c37fb0..09deb7b25ed3 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php
@@ -209,7 +209,7 @@ function build_form(array $form, array &$form_state) {
     $this->build_sorts($form, $form_state);
 
     $form['displays']['page'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#attributes' => array('class' => array('views-attachment', 'fieldset-no-legend')),
       '#tree' => TRUE,
     );
@@ -246,7 +246,7 @@ function build_form(array $form, array &$form_state) {
       '#field_prefix' => $path_prefix,
     );
     $form['displays']['page']['options']['style'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#attributes' => array('class' => array('container-inline', 'fieldset-no-legend')),
     );
 
@@ -352,7 +352,7 @@ function build_form(array $form, array &$form_state) {
     }
 
     $form['displays']['block'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#attributes' => array('class' => array('views-attachment', 'fieldset-no-legend')),
       '#tree' => TRUE,
     );
@@ -383,7 +383,7 @@ function build_form(array $form, array &$form_state) {
       '#type' => 'textfield',
     );
     $form['displays']['block']['options']['style'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#attributes' => array('class' => array('container-inline', 'fieldset-no-legend')),
     );
 
diff --git a/core/modules/views/views_ui/admin.inc b/core/modules/views/views_ui/admin.inc
index 12837b2c1131..50bdfedb59fe 100644
--- a/core/modules/views/views_ui/admin.inc
+++ b/core/modules/views/views_ui/admin.inc
@@ -332,7 +332,7 @@ function views_ui_build_preview(ViewUI $view, $display_id) {
 }
 
 /**
- * Move form elements into fieldsets for presentation purposes.
+ * Move form elements into details for presentation purposes.
  *
  * Many views forms use #tree = TRUE to keep their values in a hierarchy for
  * easier storage. Moving the form elements into fieldsets during form building
@@ -1863,7 +1863,7 @@ function views_ui_admin_settings_basic($form, &$form_state) {
   );
 
   $form['live_preview'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Live preview settings'),
   );
 
@@ -1949,7 +1949,7 @@ function views_ui_admin_settings_advanced() {
   $config = config('views.settings');
 
   $form['cache'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Caching'),
   );
 
@@ -1967,7 +1967,7 @@ function views_ui_admin_settings_advanced() {
   );
 
   $form['debug'] = array(
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#title' => t('Debugging'),
   );
 
@@ -2015,7 +2015,7 @@ function views_ui_admin_settings_advanced() {
   $options = views_fetch_plugin_names('display_extender');
   if (!empty($options)) {
     $form['extenders'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
     );
     ;
     $form['extenders']['display_extenders'] = array(
diff --git a/core/modules/views/views_ui/css/views-admin-rtl.css b/core/modules/views/views_ui/css/views-admin-rtl.css
index d98a6c0f08fb..b4039a33164b 100644
--- a/core/modules/views/views_ui/css/views-admin-rtl.css
+++ b/core/modules/views/views_ui/css/views-admin-rtl.css
@@ -47,17 +47,12 @@
 
 /* @end */
 
-/* @group Attachment details collapsible fieldset */
+/* @group Attachment collapsible details */
 
-.views-display-tab .fieldset-legend {
+.views-display-tab summary {
   left: auto;
 }
 
-.views-display-columns fieldset .fieldset-legend {
-  padding-left: inherit;
-  padding-right: 0;
-}
-
 /* @end */
 
 /* @group Attachment configuration columns */
diff --git a/core/modules/views/views_ui/css/views-admin.css b/core/modules/views/views_ui/css/views-admin.css
index dfb22a99b861..5bca0b8adcb6 100644
--- a/core/modules/views/views_ui/css/views-admin.css
+++ b/core/modules/views/views_ui/css/views-admin.css
@@ -140,19 +140,19 @@
   text-decoration: line-through;
 }
 
-.views-display-deleted > fieldset > legend,
-.views-display-deleted .fieldset-wrapper > .views-ui-display-tab-bucket > *,
+.views-display-deleted > details > summary,
+.views-display-deleted .details-wrapper > .views-ui-display-tab-bucket > *,
 .views-display-deleted .views-display-columns {
   opacity: 0.25;
 }
 
-.views-display-disabled > fieldset > legend,
-.views-display-disabled .fieldset-wrapper > .views-ui-display-tab-bucket > *,
+.views-display-disabled > details > summary,
+.views-display-disabled .details-wrapper > .views-ui-display-tab-bucket > *,
 .views-display-disabled .views-display-columns {
   opacity: 0.5;
 }
 
-.views-display-tab .fieldset-wrapper > .views-ui-display-tab-bucket .actions {
+.views-display-tab .details-wrapper > .views-ui-display-tab-bucket .actions {
   opacity: 1.0;
 }
 
@@ -182,32 +182,15 @@
 
 /* @end */
 
-/* @group Attachment details collapsible fieldset */
+/* @group Attachment collapsible details */
 
-.views-display-tab .fieldset-legend {
-  position: relative;
-}
-
-.views-display-tab .fieldset-wrapper {
-  position: relative;
-}
-
-.views-display-columns fieldset {
+.views-display-columns details {
   border: none;
   margin: 0;
   padding: 0;
 }
 
-.views-display-columns fieldset .fieldset-legend {
-  padding-left: 0; /* LTR */
-}
-
-.views-display-columns .fieldset-legend {
-  margin-top: 0;
-  padding: 6px 0;
-}
-
-.views-display-columns .fieldset-wrapper {
+.views-display-columns .details-wrapper {
   padding: 0;
 }
 
@@ -216,7 +199,7 @@
   box-sizing: border-box;
 }
 
-.js .views-display-column fieldset.collapsed {
+.js .views-display-column details.collapsed {
   height: auto;
 }
 
diff --git a/core/modules/views/views_ui/css/views-admin.theme-rtl.css b/core/modules/views/views_ui/css/views-admin.theme-rtl.css
index 99c8c42b7782..c4c89b178c90 100644
--- a/core/modules/views/views_ui/css/views-admin.theme-rtl.css
+++ b/core/modules/views/views_ui/css/views-admin.theme-rtl.css
@@ -72,7 +72,7 @@
 }
 
 .container-inline > * + *,
-.container-inline .fieldset-wrapper > * + * {
+.container-inline .details-wrapper > * + * {
   padding-left: 0;
   padding-right: 4px;
 }
@@ -122,13 +122,13 @@
 
 /* @end */
 
-/* @group Attachment details collapsible fieldset
+/* @group Attachment collapsible details
  *
- * The attachment details section is a collapsible fieldset, but should not
+ * The attachment section is a collapsible details, but should not
  * have a border around it.
  */
 
-.views-display-tab .fieldset-legend {
+.views-display-tab summary {
   left: auto;
   right: -5px;
 }
diff --git a/core/modules/views/views_ui/css/views-admin.theme.css b/core/modules/views/views_ui/css/views-admin.theme.css
index a565b473ca65..cbeb5e6f491a 100644
--- a/core/modules/views/views_ui/css/views-admin.theme.css
+++ b/core/modules/views/views_ui/css/views-admin.theme.css
@@ -150,11 +150,11 @@
 
 /* @group Forms */
 
-fieldset.box-padding {
+details.box-padding {
   border: none;
 }
 
-.views-admin fieldset fieldset {
+.views-admin details details {
   margin-bottom: 0;
 }
 
@@ -183,17 +183,17 @@ input.form-radio {
 }
 
 .container-inline > * + *,
-.container-inline .fieldset-wrapper > * + * {
+.container-inline .details-wrapper > * + * {
   padding-left: 4px; /* LTR */
 }
 
-.views-admin fieldset fieldset.container-inline {
+.views-admin details details.container-inline {
   margin-bottom: 1em;
   margin-top: 1em;
   padding-top: 0;
 }
 
-.views-admin fieldset fieldset.container-inline > .fieldset-wrapper {
+.views-admin details details.container-inline > .details-wrapper {
   padding-bottom: 0;
 }
 
@@ -385,9 +385,9 @@ td.group-title {
   padding-right: 10px;
 }
 
-/* This keeps the collapsible fieldsets of options from crashing into the bottom
+/* This keeps the collapsible details of options from crashing into the bottom
  * of the edit option columns. Because the edit option columns are floated, the collapsible
- * fieldsets need to be floated as well so that the margin above the fieldset interacts with
+ * details need to be floated as well so that the margin above the details interacts with
  * the float edit option columns.
  */
 #edit-options .collapsible {
@@ -570,10 +570,6 @@ ul#views-display-menu-tabs li.add ul.action-list li{
    margin-top: 0;
  }
 
-.views-display-column fieldset.collapsible legend {
-  font-size: 13px;
-}
-
  /* @end */
 
 /* @group Auto preview
@@ -591,7 +587,7 @@ ul#views-display-menu-tabs li.add ul.action-list li{
   margin-left: 2px;
 }
 
-#views-ui-preview-form .form-type-textfield {
+#views-ui-preview-form .form-type-textfield, #views-ui-preview-form .form-actions {
   margin-top: 5px;
 }
 
@@ -727,11 +723,11 @@ ul#views-display-menu-tabs li.add ul.action-list li{
  * The preview controls and the preview pane
  */
 
-#edit-displays-preview-controls .fieldset-wrapper > * {
+#edit-displays-preview-controls .details-wrapper > * {
   float: left;
 }
 
-#edit-displays-preview-controls .fieldset-wrapper > .form-item {
+#edit-displays-preview-controls .details-wrapper > .form-item {
   margin-top: 0.3333em;
 }
 
@@ -884,7 +880,7 @@ ul#views-display-menu-tabs li.add ul.action-list li{
   padding: 8px 13px;
 }
 
-.views-ui-dialog fieldset .item-list {
+.views-ui-dialog details .item-list {
   padding-left: 2em;
 }
 
diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewAddFormController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewAddFormController.php
index d8db8ef4796a..a20606dd1593 100644
--- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewAddFormController.php
+++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewAddFormController.php
@@ -31,7 +31,7 @@ public function form(array $form, array &$form_state, EntityInterface $view) {
     $form['#attributes']['class'] = array('views-admin');
 
     $form['name'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#attributes' => array('class' => array('fieldset-no-legend')),
     );
 
@@ -80,7 +80,7 @@ public function form(array $form, array &$form_state, EntityInterface $view) {
     // Create the part of the form that allows the user to select the basic
     // properties of what the view will display.
     $form['displays']['show'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#tree' => TRUE,
       '#attributes' => array('class' => array('container-inline')),
     );
diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php
index 853d5c9a0016..80957a96c931 100644
--- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php
+++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php
@@ -456,13 +456,13 @@ public function getDisplayDetails($view, $display) {
     $build['columns']['second']['footer'] = array();
     $build['columns']['second']['pager'] = array();
 
-    // The third column buckets are wrapped in a fieldset.
+    // The third column buckets are wrapped in details.
     $build['columns']['third'] = array(
-      '#type' => 'fieldset',
+      '#type' => 'details',
       '#title' => t('Advanced'),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
-      '#theme_wrappers' => array('fieldset', 'container'),
+      '#theme_wrappers' => array('details', 'container'),
       '#attributes' => array(
         'class' => array(
           'views-display-column',
@@ -471,7 +471,7 @@ public function getDisplayDetails($view, $display) {
       ),
     );
 
-    // Collapse the fieldset by default.
+    // Collapse the details by default.
     if (config('views.settings')->get('ui.show.advanced_column')) {
       $build['columns']['third']['#collapsed'] = FALSE;
     }
diff --git a/core/themes/bartik/css/style-rtl.css b/core/themes/bartik/css/style-rtl.css
index 74f2950c1b8c..cdd3f1d4a215 100644
--- a/core/themes/bartik/css/style-rtl.css
+++ b/core/themes/bartik/css/style-rtl.css
@@ -211,9 +211,6 @@ ul.action-links li a {
 
 /* -------------- Form Elements   ------------- */
 
-.fieldset-legend span.summary {
-  margin-left: 0;
-}
 #user-profile-form input#edit-submit {
   margin-left: 0;
 }
@@ -294,7 +291,7 @@ ul.action-links li a {
 
 /* @group Collapsible */
 
-.views-display-columns fieldset .fieldset-legend {
+.views-display-columns details summary {
   padding: 0 2px 4px 0;
 }
 
diff --git a/core/themes/bartik/css/style.css b/core/themes/bartik/css/style.css
index ffe0629027e5..a748fd410b05 100644
--- a/core/themes/bartik/css/style.css
+++ b/core/themes/bartik/css/style.css
@@ -1116,83 +1116,35 @@ a.button:active {
 
 /* -------------- Form Elements   ------------- */
 
-fieldset {
-  background: #ffffff;
-  border: 1px solid #cccccc;
-  margin-top: 10px;
-  margin-bottom: 32px;
-  padding: 0 0 10px;
-  position: relative;
-  top: 12px; /* Offsets the negative margin of legends */
+details,
+fieldset,
+.filter-wrapper {
   border-radius: 4px;
 }
-.fieldset-wrapper {
-  margin-top: 25px;
-}
-.node-form .vertical-tabs .fieldset-wrapper {
-  margin-top: 0;
-}
 .filter-wrapper {
-  top: 0;
-  padding: 1em 0 0.2em;
   border-top-left-radius: 0;
   border-top-right-radius: 0;
 }
 .filter-help a {
   font-size: 0.857em;
-  padding: 2px 20px 0;
 }
 .filter-wrapper .form-item label {
   margin-right: 10px;
 }
-.filter-wrapper .form-item {
-  padding: 0 0 0.5em 0.5em;
-}
-.filter-guidelines {
-  padding: 0 1.5em 0 0.5em;
-}
-fieldset.collapsed {
-  background: transparent;
-  border-radius: 0;
-}
-fieldset legend {
+summary {
   background: #dbdbdb;
-  border: 1px solid #ccc;
-  border-bottom: none;
   color: #3b3b3b;
-  display: block;
-  height: 2em;
-  left: -1px; /* LTR */
-  font-family: "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
-  line-height: 2;
-  padding: 0;
-  position: absolute;
-  text-indent: 10px;
   text-shadow: 0 1px 0 #fff;
-  top: -12px;
-  width: 100%;
-  border-top-left-radius: 4px;
-  border-top-right-radius: 4px;
 }
-fieldset.collapsed legend {
-  border-radius: 4px;
-}
-fieldset legend a {
+details summary a {
   color: #3b3b3b;
 }
-fieldset legend a:hover,
-fieldset legend a:focus,
-fieldset legend a:active {
+details summary a:hover,
+details summary a:focus,
+details summary a:active {
   color: #000;
 }
-fieldset .fieldset-wrapper {
-  padding: 0 10px;
-}
-fieldset .fieldset-description {
-  margin-top: 5px;
-  margin-bottom: 1em;
-  line-height: 1.4;
-  color: #3c3c3c;
+details .details-description {
   font-style: italic;
 }
 input {
@@ -1228,10 +1180,6 @@ input.form-submit:focus {
 .password-suggestions ul li {
   margin-left: 1.2em; /* LTR */
 }
-.form-item {
-  margin-bottom: 1em;
-  margin-top: 2px;
-}
 .form-item label {
   font-size: 0.929em;
 }
@@ -1352,7 +1300,7 @@ input.form-submit:focus {
   border-top-left-radius: 4px;
   border-top-right-radius: 4px;
 }
-.comment-form fieldset.filter-wrapper .fieldset-wrapper,
+.comment-form details.filter-wrapper .details-wrapper,
 .comment-form .text-format-wrapper .form-item {
   margin-top: 0;
   margin-bottom: 0;
@@ -1364,7 +1312,7 @@ input.form-submit:focus {
 .filter-wrapper .form-select {
   min-width: 120px;
 }
-.comment-form fieldset.filter-wrapper .tips {
+.comment-form details.filter-wrapper .tips {
   font-size: 0.786em;
 }
 #comment-body-add-more-wrapper .form-type-textarea label {
@@ -1383,9 +1331,6 @@ div.password-suggestions {
   background: #222222;
   opacity: 0.7;
 }
-div.vertical-tabs .vertical-tabs-panes fieldset.vertical-tabs-pane {
-  padding: 1em;
-}
 #forum .name {
   font-size: 1.083em;
 }
@@ -1503,10 +1448,10 @@ div.add-or-remove-shortcuts {
   margin: 0 5px;
 }
 /* Fix spacing when Seven is used in the overlay. */
-#system-theme-settings fieldset {
+#system-theme-settings details {
   padding: 0;
 }
-#system-theme-settings fieldset .fieldset-legend {
+#system-theme-settings details summary {
   margin-top: 0;
 }
 /* Configuration. */
@@ -1821,11 +1766,11 @@ div.admin-panel .description {
 
 /* @end */
 
-.views-display-column .fieldset-wrapper {
+.views-display-column .details-wrapper {
   margin-top: 0;
 }
 
-.views-display-column fieldset legend {
+.views-display-column details summary {
   background: none;
   border: none;
   font-family: inherit;
@@ -1837,11 +1782,11 @@ div.admin-panel .description {
   top: 3px;
 }
 
-.views-display-columns fieldset {
+.views-display-columns details {
   position: inherit;
 }
 
-.views-display-columns fieldset .fieldset-legend {
+.views-display-columns details summary {
   padding: 0 0 4px 2px; /* LTR */
 }
 
diff --git a/core/themes/seven/ie.css b/core/themes/seven/ie.css
index d1a71cefa9bc..21252de7101d 100644
--- a/core/themes/seven/ie.css
+++ b/core/themes/seven/ie.css
@@ -1,9 +1,3 @@
-/* IE renders absolute positioned legend where fieldset content starts. */
-fieldset .fieldset-legend {
-  left: 0;
-  top: 0;
-}
-
 /* IE renders monospace font too big. */
 code,
 pre,
diff --git a/core/themes/seven/style-rtl.css b/core/themes/seven/style-rtl.css
index 4974785ae60f..89303705a442 100644
--- a/core/themes/seven/style-rtl.css
+++ b/core/themes/seven/style-rtl.css
@@ -99,26 +99,7 @@ tr td:last-child {
   border-right: none;
 }
 
-/**
- * Fieldsets.
- */
-fieldset {
-  padding: 2.5em 0 0 0;
-}
-fieldset .fieldset-legend {
-  padding-right: 15px;
-  right: 0;
-}
-fieldset .fieldset-wrapper {
-  padding: 0 15px 13px 13px;
-}
-
 /* Filter */
-.filter-wrapper .form-item,
-.filter-wrapper .filter-guidelines,
-.filter-wrapper .filter-help {
-  padding: 2px 0 0 0;
-}
 ul.tips li {
   margin: 0.25em 1.5em 0.25em 0;
 }
diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css
index e8ad0cf93c94..d74f50278b9d 100644
--- a/core/themes/seven/style.css
+++ b/core/themes/seven/style.css
@@ -20,8 +20,10 @@ hr {
   height: 1px;
   background: #cccccc;
 }
+summary,
 legend {
   font-weight: bold;
+  text-transform: uppercase;
 }
 h1,
 h2,
@@ -493,50 +495,21 @@ tr td:last-child {
     display: none;
   }
 }
+
 /**
- * Fieldsets.
- *
- * Fieldset legends are displayed like containers in Seven. However, several
- * browsers do not support styling of LEGEND elements. To achieve the desired
- * styling:
- * - All fieldsets use 'position: relative'.
- * - All legend labels are wrapped in a single span.fieldset-legend that uses
- *   'position: absolute', which means that the LEGEND element itself is not
- *   rendered by browsers.
- * - Due to using 'position: absolute', collapsed fieldsets do not have a
- *   height; the fieldset requires a 'padding-top' to make the absolute
- *   positioned .fieldset-legend appear as though it would have a height.
- * - Various browsers are positioning the legend differently if there is a
- *   'padding-left'/'padding-right' applied on a fieldset and inherit the
- *   positioning even to absolute positioned elements within; we therefore have
- *   to apply all padding to the inner .fieldset-wrapper instead.
+ * Collapsible details.
  */
-fieldset {
-  border: 1px solid #ccc;
-  padding: 2.5em 0 0 0; /* LTR */
-  position: relative;
-  margin: 1em 0;
+details {
+  line-height: 1.295em;
 }
-fieldset .fieldset-legend {
-  margin-top: 0.5em;
-  padding-left: 15px; /* LTR */
-  position: absolute;
-  text-transform: uppercase;
-}
-fieldset .fieldset-wrapper {
-  padding: 0 13px 13px 15px; /* LTR */
-}
-fieldset.collapsed {
-  background-color: transparent;
-}
-.js fieldset.collapsed {
-  border-width: 1px;
-  height: auto;
+details summary {
+  padding-top: 0.5em;
+  padding-bottom: 0.5em;
 }
-fieldset fieldset {
+details details {
   background-color: #fff;
 }
-fieldset fieldset fieldset {
+details details details {
   background-color: #f8f8f8;
 }
 
@@ -544,22 +517,11 @@ fieldset fieldset fieldset {
  * Form elements.
  */
 .form-item {
-  padding: 9px 0;
-  margin: 0 0 10px;
-}
-.filter-wrapper .form-item,
-div.teaser-checkbox .form-item,
-.form-item .form-item {
-  padding: 5px 0;
-  margin: 0;
-  border: 0;
+  margin: 1em 0;
 }
 .form-type-checkbox {
   padding: 0;
 }
-.text-format-wrapper .form-item {
-  padding-bottom: 0;
-}
 .form-item label {
   margin: 0;
   padding: 0;
@@ -588,17 +550,7 @@ div.teaser-checkbox .form-item,
 
 /* Filter */
 .filter-wrapper {
-  border-top: 0;
-  padding: 10px 2px;
-}
-.filter-wrapper .fieldset-wrapper {
-  padding: 0 6px;
-}
-.filter-wrapper .form-item,
-.filter-wrapper .filter-guidelines,
-.filter-wrapper .filter-help {
   font-size: 0.923em;
-  padding: 2px 0 0 0; /* LTR */
 }
 ul.tips,
 div.description,
@@ -819,7 +771,7 @@ a.button.add:active {
     margin-bottom: 2px;
     width: 100%;
   }
-  fieldset .fieldset-legend {
+  details summary {
     overflow: hidden;
     text-overflow: ellipsis;
     white-space: nowrap;
@@ -1141,29 +1093,29 @@ div.add-or-remove-shortcuts {
 
 /* @group Forms */
 
-fieldset fieldset {
-  border: medium none;
-}
-
 /**
- * Seven positions the legend absolutely, but does not have a way to ignore
- * fieldsets without a legend so we make one up.
+ * Seven positions the summary absolutely, but does not have a way to ignore
+ * details without a summary so we make one up.
+ *
+ * @todo Neither a fieldset without legend nor a details without summary is
+ *   valid HTML markup in any way. Refactor Views UI to not produce such invalid
+ *   markup.
  */
-fieldset.fieldset-no-legend {
+details.fieldset-no-legend {
   padding-top: 0;
 }
 
 /**
  * Being extra safe here and scoping this to the add view wizard form (where
- * a layout problem occurs for the Display format fieldset if we don't fix its
+ * a layout problem occurs for the Display format details if we don't fix its
  * padding), but it's probably safe to just let it apply everywhere.
  */
-#views-ui-add-form fieldset fieldset .fieldset-wrapper {
+#views-ui-add-form details details .details-wrapper {
   padding-left: 0;
   padding-right: 0;
 }
 
-.views-display-tab fieldset.box-padding .fieldset-wrapper {
+.views-display-tab details.box-padding .details-wrapper {
   padding: 0;
 }
 
@@ -1435,7 +1387,7 @@ fieldset.fieldset-no-legend {
   top: -1px;
 }
 
-.views-ui-dialog fieldset.collapsible:not(.collapsed) {
+.views-ui-dialog details.collapsible:not(.collapsed) {
   padding-top: 1.5em;
 }
 
diff --git a/core/themes/seven/vertical-tabs-rtl.css b/core/themes/seven/vertical-tabs-rtl.css
index a9598c36a05a..cff18cbf7fa2 100644
--- a/core/themes/seven/vertical-tabs-rtl.css
+++ b/core/themes/seven/vertical-tabs-rtl.css
@@ -16,6 +16,5 @@ div.vertical-tabs ul li.selected a:active {
   border-left-color: #fff;
 }
 div.vertical-tabs .vertical-tabs-panes {
-  margin: 0 265px 0 0;
-  padding: 10px 0 10px 15px;
+  margin: 0 245px 0 0;
 }
diff --git a/core/themes/seven/vertical-tabs.css b/core/themes/seven/vertical-tabs.css
index e89f3f57edfb..6a1ee7f7d5c2 100644
--- a/core/themes/seven/vertical-tabs.css
+++ b/core/themes/seven/vertical-tabs.css
@@ -8,7 +8,7 @@ div.vertical-tabs {
   margin: 10px 0;
   position: relative;
 }
-fieldset.vertical-tabs-pane {
+.vertical-tabs-pane {
   border: 0;
   padding: 0;
   margin: 0;
@@ -66,15 +66,11 @@ div.vertical-tabs ul li.selected a:focus strong {
   text-decoration: underline;
 }
 div.vertical-tabs .vertical-tabs-panes {
-  margin: 0 0 0 265px; /* LTR */
-  padding: 10px 15px 10px 0; /* LTR */
+  margin: 0 0 0 245px; /* LTR */
 }
-fieldset.vertical-tabs-pane > legend {
+.vertical-tabs-pane > summary {
   display: none;
 }
-.vertical-tabs-pane .fieldset-wrapper > div:first-child {
-  padding-top: 5px;
-}
 
 /**
  * Prevent text inputs from overflowing when container is too narrow. "width" is
@@ -82,7 +78,7 @@ fieldset.vertical-tabs-pane > legend {
  * with "box-sizing" to prevent box model issues from occurring in most browsers.
 */
 .vertical-tabs .form-type-textfield input {
-  width: 100%;
+  max-width: 100%;
   -moz-box-sizing: border-box;
   -webkit-box-sizing: border-box;
   box-sizing: border-box;
diff --git a/core/update.php b/core/update.php
index 4e74c0c6cba8..5f88cb60e311 100644
--- a/core/update.php
+++ b/core/update.php
@@ -68,7 +68,7 @@ function update_script_selection_form($form, &$form_state) {
   $incompatible_count = 0;
   $form['start'] = array(
     '#tree' => TRUE,
-    '#type' => 'fieldset',
+    '#type' => 'details',
     '#collapsed' => TRUE,
     '#collapsible' => TRUE,
   );
-- 
GitLab