diff --git a/core/lib/Drupal/Core/Render/Element/Actions.php b/core/lib/Drupal/Core/Render/Element/Actions.php
index 2e75165..bb490f5 100644
--- a/core/lib/Drupal/Core/Render/Element/Actions.php
+++ b/core/lib/Drupal/Core/Render/Element/Actions.php
@@ -32,12 +32,16 @@ class Actions extends Container {
   public function getInfo() {
     $class = get_class($this);
     return [
+      '#optional' => FALSE,
       '#process' => [
         // @todo Move this to #pre_render.
         [$class, 'preRenderActionsDropbutton'],
         [$class, 'processActions'],
         [$class, 'processContainer'],
       ],
+      '#pre_render' => [
+        [$class, 'preRenderContainer'],
+      ]
       '#weight' => 100,
       '#theme_wrappers' => ['container'],
     ];
diff --git a/core/lib/Drupal/Core/Render/Element/Container.php b/core/lib/Drupal/Core/Render/Element/Container.php
index 212000d..3538d3f 100644
--- a/core/lib/Drupal/Core/Render/Element/Container.php
+++ b/core/lib/Drupal/Core/Render/Element/Container.php
@@ -4,6 +4,7 @@
 
 use Drupal\Component\Utility\Html as HtmlUtility;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element;
 
 /**
  * Provides a render element that wraps child elements in a container.
@@ -11,6 +12,10 @@
  * Surrounds child elements with a <div> and adds attributes such as classes or
  * an HTML ID.
  *
+ * Properties:
+ * - #optional: Indicates whether the container should not render when it has
+ *   no visible children. Defaults to FALSE.
+ *
  * Usage example:
  * @code
  * $form['needs_accommodation'] = array(
@@ -46,12 +51,14 @@ class Container extends RenderElement {
   public function getInfo() {
     $class = get_class($this);
     return [
+      '#optional' => FALSE,
       '#process' => [
         [$class, 'processGroup'],
         [$class, 'processContainer'],
       ],
       '#pre_render' => [
         [$class, 'preRenderGroup'],
+        [$class, 'preRenderContainer'],
       ],
       '#theme_wrappers' => ['container'],
     ];
@@ -79,4 +86,22 @@ public static function processContainer(&$element, FormStateInterface $form_stat
     return $element;
   }
 
+  /**
+   * Prevents optional containers from rendering if they have no children.
+   *
+   * @param $element
+   *   An associative array containing the properties and children of the
+   *   container.
+   *
+   * @return array
+   *   The modified element.
+   */
+  public static function preRenderContainer($element) {
+    // Do not render optional container elements if there are no children.
+    if (!empty($element['#printed']) && !empty($element['#optional']) && !Element::getVisibleChildren($element)) {
+      $element['#printed'] = TRUE;
+    }
+    return $element;
+  }
+
 }
diff --git a/core/modules/system/tests/modules/form_test/form_test.routing.yml b/core/modules/system/tests/modules/form_test/form_test.routing.yml
index 2250a0b..b688779 100644
--- a/core/modules/system/tests/modules/form_test/form_test.routing.yml
+++ b/core/modules/system/tests/modules/form_test/form_test.routing.yml
@@ -489,3 +489,11 @@ form_test.get_form:
     _form: '\Drupal\form_test\Form\FormTestGetForm'
   requirements:
     _access: 'TRUE'
+
+form_test.optional_container:
+  path: '/form-test/optional-container'
+  defaults:
+    _form: '\Drupal\form_test\Form\FormTestOptionalContainerForm'
+    _title: 'Optional container testing'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestOptionalContainerForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestOptionalContainerForm.php
new file mode 100644
index 0000000..4f60771
--- /dev/null
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestOptionalContainerForm.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Drupal\form_test\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Builds a simple form to test the #optional property on #type 'container'.
+ */
+class FormTestOptionalContainerForm extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'form_test_optional_container';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    // Empty containers.
+    $form['empty_optional'] = [
+      '#type' => 'container',
+      '#attributes' => ['class' => ['empty_optional']],
+      '#optional' => TRUE,
+    ];
+    $form['empty_nonoptional'] = [
+      '#type' => 'container',
+      '#attributes' => ['class' => ['empty_nonoptional']],
+      '#optional' => FALSE,
+    ];
+
+    // Non-empty containers
+    $form['nonempty_optional'] = [
+      '#type' => 'container',
+      '#attributes' => ['class' => ['nonempty_optional']],
+      '#optional' => TRUE,
+      'child' => [],
+    ];
+    $form['nonempty_nonoptional'] = [
+      '#type' => 'container',
+      '#attributes' => ['class' => ['nonempty_nonoptional']],
+      '#optional' => FALSE,
+      'child' => [],
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+  }
+
+}
diff --git a/core/modules/system/tests/src/Functional/Form/ElementsContainerTest.php b/core/modules/system/tests/src/Functional/Form/ElementsContainerTest.php
new file mode 100644
index 0000000..a7d404b
--- /dev/null
+++ b/core/modules/system/tests/src/Functional/Form/ElementsContainerTest.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Drupal\Tests\system\Functional\Form;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Tests the container form element for expected behavior.
+ *
+ * @group Form
+ */
+class ElementsContainerTest extends BrowserTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['form_test'];
+
+  /**
+   * Tests the #optional container property.
+   */
+  public function testOptionalContainerElements() {
+    $this->drupalGet('form-test/optional-container');
+    $assertSession = $this->assertSession();
+    $assertSession->elementNotExists('css', 'div.empty_optional');
+    $assertSession->elementExists('css', 'div.empty_nonoptional');
+    $assertSession->elementExists('css', 'div.nonempty_optional');
+    $assertSession->elementExists('css', 'div.nonempty_nonoptional');
+  }
+
+}
