diff --git a/core/modules/inline_form_errors/inline_form_errors.module b/core/modules/inline_form_errors/inline_form_errors.module
index 52e572d..ed8b2f5 100644
--- a/core/modules/inline_form_errors/inline_form_errors.module
+++ b/core/modules/inline_form_errors/inline_form_errors.module
@@ -5,6 +5,8 @@
  * Enables inline form errors.
  */
 
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element\FormElementInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
@@ -49,6 +51,50 @@ function inline_form_errors_preprocess_datetime_wrapper(&$variables) {
 }
 
 /**
+ * Implements hook_element_info_alter().
+ */
+function inline_form_errors_element_info_alter(array &$info) {
+  // Define a list of elements that are not form elements but are primarily
+  // used in forms and supported by Inline Form Errors.
+  $pseudo_form_elements = [
+    'details',
+    'fieldset',
+    'datetime_wrapper',
+  ];
+
+  // Add a processor for form elements and pseudo form elements.
+  foreach ($info as $element_type => $element_info) {
+    if (in_array($element_type, $pseudo_form_elements) || _inline_form_errors_element_is_form_element($element_type)) {
+      $info[$element_type]['#process'][] = 'inline_form_errors_process_form_element';
+    }
+  }
+}
+
+/**
+ * Process all form elements and pseudo form elements.
+ *
+ * @param array $element
+ *   An associative array containing the properties and children of the
+ *   element. Note that $element must be taken by reference here, so processed
+ *   child elements are taken over into $form_state.
+ * @param \Drupal\Core\Form\FormStateInterface $form_state
+ *   The current state of the form.
+ * @param array $complete_form
+ *   The complete form structure.
+ *
+ * @return array
+ *   The processed element.
+ */
+function inline_form_errors_process_form_element(array &$element, FormStateInterface $form_state, array &$complete_form) {
+  // Prevent displaying inline form errors when disabled for the whole form.
+  if (!empty($complete_form['#disable_inline_form_errors'])) {
+    $element['#error_no_message'] = TRUE;
+  }
+
+  return $element;
+}
+
+/**
  * Populates form errors in the template.
  */
 function _inline_form_errors_set_errors(&$variables) {
@@ -57,3 +103,25 @@ function _inline_form_errors_set_errors(&$variables) {
     $variables['errors'] = $element['#errors'];
   }
 }
+
+/**
+ * Determine if a render element type also is a form element.
+ *
+ * @param string $element_type
+ *   The element type.
+ *
+ * @return bool
+ *   TRUE if the given element type is a form element or FALSE otherwise.
+ */
+function _inline_form_errors_element_is_form_element($element_type) {
+  /* @var \Drupal\Core\Render\ElementInfoManager $manager */
+  $manager = \Drupal::service('plugin.manager.element_info');
+  $element_definitions = $manager->getDefinitions();
+
+  if (!empty($element_definitions[$element_type])) {
+    $element = $manager->createInstance($element_type);
+    return $element instanceof FormElementInterface;
+  }
+
+  return FALSE;
+}
diff --git a/core/modules/inline_form_errors/src/FormErrorHandler.php b/core/modules/inline_form_errors/src/FormErrorHandler.php
index 2b892e9..9c23f43 100644
--- a/core/modules/inline_form_errors/src/FormErrorHandler.php
+++ b/core/modules/inline_form_errors/src/FormErrorHandler.php
@@ -47,15 +47,18 @@ public function __construct(TranslationInterface $string_translation, LinkGenera
   /**
    * Loops through and displays all form errors.
    *
+   * To disable inline form errors for a complete form set the
+   * '$form[#disable_inline_form_errors]' property to TRUE. This should only be
+   * done when another appropriate accessibility strategy is in place.
+   *
    * @param array $form
    *   An associative array containing the structure of the form.
    * @param \Drupal\Core\Form\FormStateInterface $form_state
    *   The current state of the form.
    */
   protected function displayErrorMessages(array $form, FormStateInterface $form_state) {
-    // Use the original error display for Quick Edit forms, because in this case
-    // the errors are already near the form element.
-    if ($form['#form_id'] === 'quickedit_field_form') {
+    // Skip generating inline form errors when opted out.
+    if (!empty($form['#disable_inline_form_errors'])) {
       parent::displayErrorMessages($form, $form_state);
       return;
     }
diff --git a/core/modules/inline_form_errors/tests/src/Kernel/FormElementInlineErrorTest.php b/core/modules/inline_form_errors/tests/src/Kernel/FormElementInlineErrorTest.php
new file mode 100644
index 0000000..31bb0ce
--- /dev/null
+++ b/core/modules/inline_form_errors/tests/src/Kernel/FormElementInlineErrorTest.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Drupal\Tests\inline_form_errors\Kernel;
+
+use Drupal\Core\Form\FormState;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests messages on form elements.
+ *
+ * @group InlineFormErrors
+ */
+class FormElementInlineErrorTest extends KernelTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['inline_form_errors'];
+
+  /**
+   * Test that form elements don't show an error when opting out.
+   */
+  public function testDisplayErrorMessagesNotInline() {
+    $form_id = 'test';
+
+    $form = [
+      '#parents' => [],
+      '#disable_inline_form_errors' => TRUE,
+      '#array_parents' => [],
+    ];
+    $form['test'] = [
+      '#type' => 'textfield',
+      '#title' => 'Test',
+      '#parents' => ['test'],
+      '#id' => 'edit-test',
+      '#array_parents' => ['test'],
+    ];
+    $form_state = new FormState();
+
+    \Drupal::formBuilder()->prepareForm($form_id, $form, $form_state);
+    \Drupal::formBuilder()->processForm($form_id, $form, $form_state);
+    \Drupal::formBuilder()->doBuildForm($form_id, $form, $form_state);
+
+    $this->assertArraySubset(['#error_no_message' => TRUE], $form['test']);
+  }
+
+}
diff --git a/core/modules/inline_form_errors/tests/src/Unit/FormErrorHandlerTest.php b/core/modules/inline_form_errors/tests/src/Unit/FormErrorHandlerTest.php
index acd255b..5b42a8f 100644
--- a/core/modules/inline_form_errors/tests/src/Unit/FormErrorHandlerTest.php
+++ b/core/modules/inline_form_errors/tests/src/Unit/FormErrorHandlerTest.php
@@ -140,12 +140,9 @@ public function testSetElementErrorsFromFormState() {
   }
 
   /**
-   * Test that Quick Edit forms show non-inline errors.
-   *
-   * @covers ::handleFormErrors
-   * @covers ::displayErrorMessages
+   * Test that opting out of inline form errors works.
    */
-  public function testDisplayErrorMessagesNotInlineQuickEdit() {
+  public function testDisplayErrorMessagesNotInline() {
     $form_error_handler = $this->getMockBuilder(FormErrorHandler::class)
       ->setConstructorArgs([$this->getStringTranslationStub(), $this->getMock(LinkGeneratorInterface::class), $this->getMock(RendererInterface::class)])
       ->setMethods(['drupalSetMessage'])
@@ -157,7 +154,7 @@ public function testDisplayErrorMessagesNotInlineQuickEdit() {
 
     $form = [
       '#parents' => [],
-      '#form_id' => 'quickedit_field_form',
+      '#disable_inline_form_errors' => TRUE,
       '#array_parents' => [],
     ];
     $form['test'] = [
@@ -165,7 +162,7 @@ public function testDisplayErrorMessagesNotInlineQuickEdit() {
       '#title' => 'Test',
       '#parents' => ['test'],
       '#id' => 'edit-test',
-      '#array_parents' => ['test']
+      '#array_parents' => ['test'],
     ];
     $form_state = new FormState();
     $form_state->setErrorByName('test', 'invalid');
diff --git a/core/modules/quickedit/src/Form/QuickEditFieldForm.php b/core/modules/quickedit/src/Form/QuickEditFieldForm.php
index ba2dac3..7603159 100644
--- a/core/modules/quickedit/src/Form/QuickEditFieldForm.php
+++ b/core/modules/quickedit/src/Form/QuickEditFieldForm.php
@@ -114,6 +114,10 @@ public function buildForm(array $form, FormStateInterface $form_state, EntityInt
       '#attributes' => ['class' => ['quickedit-form-submit']],
     ];
 
+    // Use the non-inline form error display for Quick Edit forms, because in
+    // this case the errors are already near the form element.
+    $form['#disable_inline_form_errors'] = TRUE;
+
     // Simplify it for optimal in-place use.
     $this->simplify($form, $form_state);
 
