diff --git a/core/includes/form.inc b/core/includes/form.inc
index 81c6406..ebe3403 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -236,9 +236,22 @@ function template_preprocess_details(&$variables) {
     $variables['summary_attributes']['aria-pressed'] = $variables['summary_attributes']['aria-expanded'];
   }
   $variables['title'] = (!empty($element['#title'])) ? $element['#title'] : '';
-  $variables['description'] = (!empty($element['#description'])) ? $element['#description'] : '';
   $variables['children'] = (isset($element['#children'])) ? $element['#children'] : '';
   $variables['value'] = (isset($element['#value'])) ? $element['#value'] : '';
+
+  $variables['description'] = NULL;
+  if (!empty($element['#description'])) {
+    $variables['description_display'] = isset($element['#description_display']) ? $element['#description_display'] : 'before';
+    $description_attributes = [];
+    if ($variables['description_display'] === 'invisible') {
+      $description_attributes['class'][] = 'visually-hidden';
+    }
+    if (!empty($element['#id'])) {
+      $description_attributes['id'] = $element['#id'] . '--description';
+    }
+    $variables['description']['attributes'] = new Attribute($description_attributes);
+    $variables['description']['content'] = $element['#description'];
+  }
 }
 
 /**
diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index a24330d..cfdff72 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -790,11 +790,12 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
       $element['#defaults_loaded'] = TRUE;
     }
     // Assign basic defaults common for all form elements.
+    // NOTE: description_display is below by default, excepted for details.
     $element += array(
       '#required' => FALSE,
       '#attributes' => array(),
       '#title_display' => 'before',
-      '#description_display' => 'after',
+      '#description_display' => (isset($element['#type']) && $element['#type'] == 'details') ? 'before' : 'after',
       '#errors' => NULL,
     );
 
diff --git a/core/modules/system/src/Tests/Form/ElementsDetailsTest.php b/core/modules/system/src/Tests/Form/ElementsDetailsTest.php
new file mode 100644
index 0000000..84d67c2
--- /dev/null
+++ b/core/modules/system/src/Tests/Form/ElementsDetailsTest.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Form\ElementsDetailsTest.
+ */
+
+namespace Drupal\system\Tests\Form;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests details element rendering and description placement.
+ *
+ * @group Form
+ */
+class ElementsDetailsTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['form_test'];
+
+  /**
+   * Tests different display options for details element descriptions.
+   */
+  function testFieldsetDescriptions() {
+    $this->drupalGet('form-test/group-details');
+
+    // Check #description default placement.
+    $field_id = 'edit-meta';
+    $description_id = $field_id . '--description';
+    $elements = $this->xpath('//details[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]//div/preceding-sibling::div');
+    $this->assertTrue(isset($elements[0]), t('Properly places by default the #description element before the form item within details group.'));
+
+    // Check #description placement with #description_display='before'.
+    $field_id = 'edit-details-before';
+    $description_id = $field_id . '--description';
+    $elements = $this->xpath('//details[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]//div[@id="edit-meta-before"]/preceding-sibling::div[@id="' . $description_id . '"]');
+    $this->assertTrue(isset($elements[0]), t('Properly places the #description element before the form item within details group.'));
+
+    // Check #description placement with #description_display='after'.
+    $field_id = 'edit-details-after';
+    $description_id = $field_id . '--description';
+    $elements = $this->xpath('//details[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]//div[@id="edit-meta-after"]/following-sibling::div[@id="' . $description_id . '"]');
+    $this->assertTrue(isset($elements[0]), t('Properly places the #description element after the form item within details group.'));
+
+    // Check if the class is 'visually-hidden' on the form details description
+    // for the option with #description_display='invisible' and also check that
+    // the description is placed after the form element.
+    $field_id = 'edit-details-invisible';
+    $description_id = $field_id . '--description';
+    $elements = $this->xpath('//details[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]//div[@id="edit-meta-invisible"]/following-sibling::div[contains(@class, "visually-hidden")]');
+    $this->assertTrue(isset($elements[0]), t('Properly renders the #description element visually-hidden within details group.'));
+  }
+}
diff --git a/core/modules/system/templates/details.html.twig b/core/modules/system/templates/details.html.twig
index 1c0fd79..7ed4bca 100644
--- a/core/modules/system/templates/details.html.twig
+++ b/core/modules/system/templates/details.html.twig
@@ -7,6 +7,12 @@
  * - attributes: A list of HTML attributes for the details element.
  * - title: (optional) The title of the element, may not be set.
  * - description: (optional) The description of the element, may not be set.
+ * - description_display: (optional) Description display setting. It can have these values:
+ *   - before: The description is output before the element. This is the default
+ *     value.
+ *   - after: The description is output after the element.
+ *   - invisible: The description is output after the element, hidden visually
+ *     but available to screen readers.
  * - children: (optional) The children of the element, may not be set.
  * - value: (optional) The value of the element, may not be set.
  *
@@ -20,7 +26,12 @@
     <summary{{ summary_attributes }}>{{ title }}</summary>
   {%- endif -%}
 
-  {{ description }}
+  <div{{ description.attributes }}>
+    {{ description.content }}
+  </div>
   {{ children }}
   {{ value }}
+  <div{{ description.attributes.addClass(description_classes) }}>
+    {{ description.content }}
+  </div>
 </details>
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupDetailsForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupDetailsForm.php
index d8f5925..667f1d8 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupDetailsForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupDetailsForm.php
@@ -34,6 +34,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     $form['meta'] = array(
       '#type' => 'details',
       '#title' => 'Group element',
+      '#description' => 'Details test for default description position.',
       '#open' => TRUE,
       '#group' => 'details',
     );
@@ -41,6 +42,53 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#type' => 'textfield',
       '#title' => 'Nest in details element',
     );
+    $form['details_before'] = [
+      '#type' => 'details',
+      '#title' => 'Details test for description before element',
+      '#description' => 'Details test for description before element.',
+      '#description_display' => 'before',
+    ];
+    $form['meta_before'] =[
+      '#type' => 'container',
+      '#title' => 'Group element',
+      '#group' => 'details_before',
+    ];
+    $form['meta_before']['element'] = [
+      '#type' => 'textfield',
+      '#title' => 'Nest in container element',
+    ];
+
+    $form['details_after'] = [
+      '#type' => 'details',
+      '#title' => 'Details test for description after element',
+      '#description' => 'Details test for description after element.',
+      '#description_display' => 'after',
+    ];
+    $form['meta_after'] = [
+      '#type' => 'container',
+      '#title' => 'Group element',
+      '#group' => 'details_after',
+    ];
+    $form['meta_after']['element'] = [
+      '#type' => 'textfield',
+      '#title' => 'Nest in container element',
+    ];
+
+    $form['details_invisible'] = [
+      '#type' => 'details',
+      '#title' => 'Details test for visually-hidden description',
+      '#description' => 'Details test for visually-hidden description.',
+      '#description_display' => 'invisible',
+    ];
+    $form['meta_invisible'] = [
+      '#type' => 'container',
+      '#title' => 'Group element',
+      '#group' => 'details_invisible',
+    ];
+    $form['meta_invisible']['element'] = [
+      '#type' => 'textfield',
+      '#title' => 'Nest in container element',
+    ];
     return $form;
   }
 
diff --git a/core/themes/classy/templates/form/details.html.twig b/core/themes/classy/templates/form/details.html.twig
index 9b149d7..530c177 100644
--- a/core/themes/classy/templates/form/details.html.twig
+++ b/core/themes/classy/templates/form/details.html.twig
@@ -18,14 +18,21 @@
     <summary{{ summary_attributes }}>{{ title }}</summary>
   {%- endif -%}
   <div class="details-wrapper">
-    {%- if description -%}
-      <div class="details-description">{{ description }}</div>
-    {%- endif -%}
+    {% if description_display == 'before' and description.content %}
+      <div{{ description.attributes }}>
+      {{ description.content }}
+      </div>
+    {% endif %}
     {%- if children -%}
       {{ children }}
     {%- endif -%}
     {%- if value -%}
       {{ value }}
     {%- endif -%}
+    {% if description_display in ['after', 'invisible'] and description.content %}
+      <div{{ description.attributes.addClass(description_classes) }}>
+        {{ description.content }}
+      </div>
+    {% endif %}
   </div>
 </details>
