diff --git a/core/includes/form.inc b/core/includes/form.inc
index 58563c6..00c0ff6 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -193,9 +193,9 @@ function template_preprocess_fieldset(&$variables) {
   Element::setAttributes($element, array('id'));
   Element\RenderElement::setAttributes($element);
   $variables['attributes'] = $element['#attributes'];
-  $variables['prefix'] = isset($element['#field_prefix']) ? $element['#field_prefix'] : NULL;
-  $variables['suffix'] = isset($element['#field_suffix']) ? $element['#field_suffix'] : NULL;
-  $variables['title_display'] = isset($element['#title_display']) ? $element['#title_display'] : NULL;
+  $variables['prefix'] = $element['#field_prefix'];
+  $variables['suffix'] = $element['#field_suffix'];
+  $variables['title_display'] = $element['#title_display'];
   $variables['children'] = $element['#children'];
   $variables['required'] = !empty($element['#required']) ? $element['#required'] : NULL;
 
@@ -204,7 +204,13 @@ function template_preprocess_fieldset(&$variables) {
   }
 
   $variables['legend']['attributes'] = new Attribute();
-  $variables['legend_span']['attributes'] = new Attribute();
+  // Add 'visually-hidden' class to legend span.
+  if ($variables['title_display'] == 'invisible') {
+    $variables['legend_span']['attributes'] = new Attribute(array('class' => 'visually-hidden'));
+  }
+  else {
+    $variables['legend_span']['attributes'] = new Attribute();
+  }
 
   if (!empty($element['#description'])) {
     $description_id = $element['#attributes']['id'] . '--description';
diff --git a/core/modules/system/src/Tests/Form/ElementsLabelsTest.php b/core/modules/system/src/Tests/Form/ElementsLabelsTest.php
index 9a09442..360cb68 100644
--- a/core/modules/system/src/Tests/Form/ElementsLabelsTest.php
+++ b/core/modules/system/src/Tests/Form/ElementsLabelsTest.php
@@ -93,6 +93,12 @@ function testFormLabels() {
     $this->assertEqual($elements[0]['title'], 'Checkboxes test' . ' (' . t('Required') . ')', 'Title attribute found.');
     $elements = $this->xpath('//div[@id="edit-form-radios-title-attribute"]');
     $this->assertEqual($elements[0]['title'], 'Radios test' . ' (' . t('Required') . ')', 'Title attribute found.');
+
+    $elements = $this->xpath('//fieldset[@id="edit-form-checkboxes-title-invisible--wrapper"]/legend/span[contains(@class, "visually-hidden")]');
+    $this->assertTrue(!empty($elements), "Title/Label not displayed when 'visually-hidden' attribute is set in checkboxes.");
+
+    $elements = $this->xpath('//fieldset[@id="edit-form-radios-title-invisible--wrapper"]/legend/span[contains(@class, "visually-hidden")]');
+    $this->assertTrue(!empty($elements), "Title/Label not displayed when 'visually-hidden' attribute is set in radios.");
   }
 
   /**
@@ -122,4 +128,27 @@ function testFormDescriptions() {
     $this->assertTrue(isset($elements[0]), t('Properly renders the #description element visually-hidden.'));
   }
 
+  /**
+   * Test forms in theme-less environments.
+   */
+  function testFormsInThemeLessEnvironments() {
+    $form = $this->getFormWithLimitedProperties();
+    $render_service = $this->container->get('renderer');
+    // This should not throw any notices.
+    $render_service->renderPlain($form);
+  }
+
+  /**
+   * Return a form with element with not all properties defined.
+   */
+  protected function getFormWithLimitedProperties() {
+    $form = array();
+
+    $form['fieldset'] = array(
+      '#type' => 'fieldset',
+      '#title' => 'Fieldset',
+    );
+
+    return $form;
+  }
 }
diff --git a/core/modules/system/src/Tests/Installer/InstallerTest.php b/core/modules/system/src/Tests/Installer/InstallerTest.php
index 5514f75..a2dd968 100644
--- a/core/modules/system/src/Tests/Installer/InstallerTest.php
+++ b/core/modules/system/src/Tests/Installer/InstallerTest.php
@@ -53,6 +53,8 @@ protected function setUpLanguage() {
   protected function setUpProfile() {
     // Assert that the expected title is present.
     $this->assertEqual('Select an installation profile', $this->cssSelect('main h2')[0]);
+    $result = $this->xpath('//span[contains(@class, :class) and contains(text(), :text)]', array(':class' => 'visually-hidden', ':text' => 'Select an installation profile'));
+    $this->assertEqual(count($result), 1, "Title/Label not displayed when '#title_display' => 'invisible' attribute is set");
 
     parent::setUpProfile();
   }
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestLabelForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestLabelForm.php
index 75234b0..ae57d4e 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestLabelForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestLabelForm.php
@@ -108,7 +108,26 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       ),
       '#required' => TRUE,
     );
-
+    $form['form_checkboxes_title_invisible'] = array(
+      '#type' => 'checkboxes',
+      '#title' => 'Checkboxes test invisible',
+      '#title_display' => 'invisible',
+      '#options' => array(
+        'first-checkbox' => 'First checkbox',
+        'second-checkbox' => 'Second checkbox',
+      ),
+      '#required' => TRUE,
+    );
+    $form['form_radios_title_invisible'] = array(
+      '#type' => 'radios',
+      '#title' => 'Radios test invisible',
+      '#title_display' => 'invisible',
+      '#options' => array(
+        'first-radio' => 'First radio',
+        'second-radio' => 'Second radio',
+      ),
+      '#required' => TRUE,
+    );
     return $form;
   }
 
