diff --git a/core/includes/form.inc b/core/includes/form.inc
index 678a640..24db0ca 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -211,14 +211,18 @@ function template_preprocess_fieldset(&$variables) {
   $variables['legend']['attributes'] = new Attribute();
   $variables['legend_span']['attributes'] = new Attribute();
 
+  $variables['description'] = NULL;
   if (!empty($element['#description'])) {
-    $description_id = $element['#attributes']['id'] . '--description';
-    $description_attributes['id'] = $description_id;
+    $variables['description_display'] = $element['#description_display'];
+    $description_attributes = [];
+    if ($element['#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'];
-
-    // Add the description's id to the fieldset aria attributes.
-    $variables['attributes']['aria-describedby'] = $description_id;
   }
 
   // Suppress error messages.
diff --git a/core/modules/language/config/optional/tour.tour.language-edit.yml b/core/modules/language/config/optional/tour.tour.language-edit.yml
index 0d37ead..df615a5 100644
--- a/core/modules/language/config/optional/tour.tour.language-edit.yml
+++ b/core/modules/language/config/optional/tour.tour.language-edit.yml
@@ -36,7 +36,7 @@ tips:
     body: '<p>Choose if the language is a "Left to right" or "Right to left" language.</p><p>Note that not all themes support "Right to left" layouts, so test your theme if you are using "Right to left".</p>'
     weight: 4
     attributes:
-      data-id: edit-direction--wrapper--description
+      data-id: edit-direction--description
   language-edit-continue:
     id: language-edit-continue
     plugin: text
diff --git a/core/modules/system/src/Tests/Form/ElementsFieldsetTest.php b/core/modules/system/src/Tests/Form/ElementsFieldsetTest.php
new file mode 100644
index 0000000..82b3d79
--- /dev/null
+++ b/core/modules/system/src/Tests/Form/ElementsFieldsetTest.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Form\ElementsFieldsetTest.
+ */
+
+namespace Drupal\system\Tests\Form;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests fieldset element rendering and description placement.
+ *
+ * @group Form
+ */
+class ElementsFieldsetTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['form_test'];
+
+  /**
+   * Tests different display options for fieldset element descriptions.
+   */
+  function testFieldsetDescriptions() {
+    $this->drupalGet('form-test/group-fieldset');
+
+    // Check #description placement with #description_display='before'.
+    $field_id = 'edit-fieldset-before';
+    $description_id = $field_id . '--description';
+    $elements = $this->xpath('//fieldset[@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.'));
+
+    // Check #description placement with #description_display='after'.
+    $field_id = 'edit-fieldset-after';
+    $description_id = $field_id . '--description';
+    $elements = $this->xpath('//fieldset[@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.'));
+
+    // Check if the class is 'visually-hidden' on the form fieldset description
+    // for the option with #description_display='invisible' and also check that
+    // the description is placed after the form element.
+    $field_id = 'edit-fieldset-invisible';
+    $description_id = $field_id . '--description';
+    $elements = $this->xpath('//fieldset[@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.'));
+  }
+}
\ No newline at end of file
diff --git a/core/modules/system/templates/fieldset.html.twig b/core/modules/system/templates/fieldset.html.twig
index b67ec85..54247e4 100644
--- a/core/modules/system/templates/fieldset.html.twig
+++ b/core/modules/system/templates/fieldset.html.twig
@@ -13,6 +13,12 @@
  * - description: The description element containing the following properties:
  *   - content: The description content of the fieldset.
  *   - attributes: HTML attributes to apply to the description container.
+ * - description_display: Description display setting. It can have these values:
+ *   - before: The description is output before the element.
+ *   - after: The description is output after the element. This is the default
+ *     value.
+ *   - invisible: The description is output after the element, hidden visually
+ *     but available to screen readers.
  * - children: The rendered child elements of the fieldset.
  * - prefix: The content to add before the fieldset children.
  * - suffix: The content to add after the fieldset children.
@@ -43,6 +49,11 @@
     <span{{ legend_span.attributes.addClass(legend_span_classes) }}>{{ legend.title }}</span>
   </legend>
   <div class="fieldset-wrapper">
+    {% if description_display == 'before' and description.content %}
+      <div{{ description.attributes }}>
+        {{ description.content }}
+      </div>
+    {% endif %}
     {% if errors %}
       <div>
         {{ errors }}
@@ -55,8 +66,10 @@
     {% if suffix %}
       <span class="field-suffix">{{ suffix }}</span>
     {% endif %}
-    {% if description.content %}
-      <div{{ description.attributes.addClass('description') }}>{{ description.content }}</div>
+    {% if description_display in ['after', 'invisible'] and description.content %}
+      <div{{ description.attributes.addClass(description_classes) }}>
+        {{ description.content }}
+      </div>
     {% endif %}
   </div>
 </fieldset>
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupFieldsetForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupFieldsetForm.php
index e55b1af..58d6136 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupFieldsetForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupFieldsetForm.php
@@ -26,19 +26,67 @@ public function getFormId() {
    * {@inheritdoc}
    */
   public function buildForm(array $form, FormStateInterface $form_state) {
-    $form['fieldset'] = array(
+    $form['fieldset'] = [
       '#type' => 'fieldset',
       '#title' => 'Fieldset',
-    );
-    $form['meta'] = array(
+    ];
+    $form['meta'] = [
       '#type' => 'container',
       '#title' => 'Group element',
       '#group' => 'fieldset',
-    );
-    $form['meta']['element'] = array(
+    ];
+    $form['meta']['element'] = [
       '#type' => 'textfield',
       '#title' => 'Nest in container element',
-    );
+    ];
+
+    $form['fieldset_before'] = [
+      '#type' => 'fieldset',
+      '#title' => 'Fieldset test for description before element',
+      '#description' => 'Fieldset test for description before element.',
+      '#description_display' => 'before',
+    ];
+    $form['meta_before'] = [
+      '#type' => 'container',
+      '#title' => 'Group element',
+      '#group' => 'fieldset_before',
+    ];
+    $form['meta_before']['element'] = [
+      '#type' => 'textfield',
+      '#title' => 'Nest in container element',
+    ];
+
+    $form['fieldset_after'] = [
+      '#type' => 'fieldset',
+      '#title' => 'Fieldset test for description after element',
+      '#description' => 'Fieldset test for description after element.',
+      '#description_display' => 'after',
+    ];
+    $form['meta_after'] = [
+      '#type' => 'container',
+      '#title' => 'Group element',
+      '#group' => 'fieldset_after',
+    ];
+    $form['meta_after']['element'] = [
+      '#type' => 'textfield',
+      '#title' => 'Nest in container element',
+    ];
+
+    $form['fieldset_invisible'] = [
+      '#type' => 'fieldset',
+      '#title' => 'Fieldset test for visually-hidden description',
+      '#description' => 'Fieldset test for visually-hidden description.',
+      '#description_display' => 'invisible',
+    ];
+    $form['meta_invisible'] = [
+      '#type' => 'container',
+      '#title' => 'Group element',
+      '#group' => 'fieldset_invisible',
+    ];
+    $form['meta_invisible']['element'] = [
+      '#type' => 'textfield',
+      '#title' => 'Nest in container element',
+    ];
     return $form;
   }
 
diff --git a/core/themes/classy/templates/form/fieldset.html.twig b/core/themes/classy/templates/form/fieldset.html.twig
index 4bd7d0a..85f5228 100644
--- a/core/themes/classy/templates/form/fieldset.html.twig
+++ b/core/themes/classy/templates/form/fieldset.html.twig
@@ -13,6 +13,12 @@
  * - description: The description element containing the following properties:
  *   - content: The description content of the fieldset.
  *   - attributes: HTML attributes to apply to the description container.
+ * - description_display: Description display setting. It can have these values:
+ *   - before: The description is output before the element.
+ *   - after: The description is output after the element. This is the default
+ *     value.
+ *   - invisible: The description is output after the element, hidden visually
+ *     but available to screen readers.
  * - children: The rendered child elements of the fieldset.
  * - prefix: The content to add before the fieldset children.
  * - suffix: The content to add after the fieldset children.
@@ -41,6 +47,11 @@
     <span{{ legend_span.attributes.addClass(legend_span_classes) }}>{{ legend.title }}</span>
   </legend>
   <div class="fieldset-wrapper">
+    {% if description_display == 'before' and description.content %}
+      <div{{ description.attributes }}>
+        {{ description.content }}
+      </div>
+    {% endif %}
     {% if errors %}
       <div class="form-item--error-message">
         <strong>{{ errors }}</strong>
@@ -53,8 +64,10 @@
     {% if suffix %}
       <span class="field-suffix">{{ suffix }}</span>
     {% endif %}
-    {% if description.content %}
-      <div{{ description.attributes.addClass('description') }}>{{ description.content }}</div>
+    {% if description_display in ['after', 'invisible'] and description.content %}
+      <div{{ description.attributes.addClass(description_classes) }}>
+        {{ description.content }}
+      </div>
     {% endif %}
   </div>
 </fieldset>
