diff --git a/core/modules/layout_builder/layout_builder.module b/core/modules/layout_builder/layout_builder.module
index 8d19c35bad..c8ebd58f84 100644
--- a/core/modules/layout_builder/layout_builder.module
+++ b/core/modules/layout_builder/layout_builder.module
@@ -26,6 +26,7 @@
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Access\AccessResult;
 use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
+use Drupal\layout_builder\QuickEditIntegration;
 
 /**
  * Implements hook_help().
@@ -147,6 +148,12 @@ function layout_builder_entity_view_alter(array &$build, EntityInterface $entity
       }
     }
   }
+
+  if (\Drupal::moduleHandler()->moduleExists('quickedit')) {
+    /** @var \Drupal\layout_builder\QuickEditIntegration $quick_edit_integration */
+    $quick_edit_integration = \Drupal::classResolver(QuickEditIntegration::class);
+    $quick_edit_integration->entityViewAlter($build, $entity, $display);
+  }
 }
 
 /**
@@ -313,3 +320,12 @@ function layout_builder_system_breadcrumb_alter(Breadcrumb &$breadcrumb, RouteMa
     $breadcrumb->addCacheableDependency($cacheability);
   }
 }
+
+/**
+ * Implements hook_quickedit_render_field().
+ */
+function layout_builder_quickedit_render_field(EntityInterface $entity, $field_name, $view_mode_id, $langcode) {
+  /** @var \Drupal\layout_builder\QuickEditIntegration $quick_edit_integration */
+  $quick_edit_integration = \Drupal::classResolver(QuickEditIntegration::class);
+  return $quick_edit_integration->quickEditRenderField($entity, $field_name, $view_mode_id, $langcode);
+}
diff --git a/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
index 8843f8fe57..d74f6648c5 100644
--- a/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
+++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
@@ -2,6 +2,9 @@
 
 namespace Drupal\layout_builder\Entity;
 
+use Drupal\Component\Plugin\ConfigurableInterface;
+use Drupal\Component\Plugin\DerivativeInspectionInterface;
+use Drupal\Component\Plugin\PluginBase;
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Entity\Entity\EntityViewDisplay as BaseEntityViewDisplay;
 use Drupal\Core\Entity\EntityStorageInterface;
@@ -13,6 +16,7 @@
 use Drupal\Core\StringTranslation\TranslatableMarkup;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\layout_builder\LayoutEntityHelperTrait;
 use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
 use Drupal\layout_builder\Section;
 use Drupal\layout_builder\SectionComponent;
@@ -29,6 +33,7 @@
 class LayoutBuilderEntityViewDisplay extends BaseEntityViewDisplay implements LayoutEntityDisplayInterface {
 
   use SectionStorageTrait;
+  use LayoutEntityHelperTrait;
 
   /**
    * The entity field manager.
@@ -470,4 +475,89 @@ private function sectionStorageManager() {
     return \Drupal::service('plugin.manager.layout_builder.section_storage');
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getComponent($name) {
+    if ($this->isLayoutBuilderEnabled() && $section_component = $this->getQuickEditSectionComponent() ?: $this->getSectionComponentForFieldName($name)) {
+      $plugin = $section_component->getPlugin();
+      if ($plugin instanceof ConfigurableInterface) {
+        $configuration = $plugin->getConfiguration();
+        if (isset($configuration['formatter'])) {
+          return $configuration['formatter'];
+        }
+      }
+    }
+    return parent::getComponent($name);
+  }
+
+  /**
+   * Returns the QuickEdit formatter settings.
+   *
+   * @return \Drupal\layout_builder\SectionComponent|null
+   *   The section component if it is available.
+   *
+   * @see \Drupal\layout_builder\QuickEditIntegration::entityViewAlter()
+   * @see \Drupal\quickedit\MetadataGenerator::generateFieldMetadata()
+   */
+  private function getQuickEditSectionComponent() {
+    // To determine the view_mode used by QuickEdit we need an originalMode set.
+    if ($original_mode = $this->getOriginalMode()) {
+      $parts = explode('-', $original_mode);
+      // The QuickEdit view_mode is created by
+      // \Drupal\layout_builder\QuickEditIntegration::entityViewAlter()
+      // by concatenating together the information we need to retrieve the
+      // Layout Builder component. The created view_mode starts with
+      // 'layout_builder' to distinguish it from other view_modes. If the third
+      // part of the is 'component' then this is a field that is rendered by
+      // Layout Builder.
+      if (count($parts) === 4 && $parts[0] === 'layout_builder' && $parts[2] === 'component') {
+        list($delta, $component_uuid, $entity_id) = explode('-', $parts[3]);
+        // @todo Explicitly cast delta to an integer, remove this in
+        //   https://www.drupal.org/project/drupal/issues/2984509.
+        $delta = (int) $delta;
+
+        $entity = $this->entityTypeManager()->getStorage($this->getTargetEntityTypeId())->load($entity_id);
+        $sections = $this->getEntitySections($entity);
+        if (isset($sections[$delta])) {
+          $component = $sections[$delta]->getComponent(str_replace('_', '-', $component_uuid));
+          $plugin = $component->getPlugin();
+          // We only care about FieldBlock because these are only components
+          // that provide QuickEdit integration.
+          if ($plugin instanceof DerivativeInspectionInterface && $plugin->getBaseId() === 'field_block') {
+            return $component;
+          }
+        }
+      }
+    }
+    return NULL;
+  }
+
+  /**
+   * Gets the component for a given field name if any.
+   *
+   * @param string $field_name
+   *   The field name.
+   *
+   * @return \Drupal\layout_builder\SectionComponent|null
+   *   The section component if it is available.
+   */
+  private function getSectionComponentForFieldName($field_name) {
+    // Loop through every component until the first match is found.
+    foreach ($this->getSections() as $section) {
+      foreach ($section->getComponents() as $component) {
+        $plugin = $component->getPlugin();
+        if ($plugin instanceof DerivativeInspectionInterface && $plugin->getBaseId() === 'field_block') {
+          // FieldBlock derivative IDs are in the format
+          // [entity_type]:[bundle]:[field].
+          list(, , $field_block_field_name) = explode(PluginBase::DERIVATIVE_SEPARATOR, $plugin->getDerivativeId());
+          if ($field_block_field_name === $field_name) {
+            return $component;
+          }
+        }
+      }
+    }
+    return NULL;
+  }
+
 }
diff --git a/core/modules/layout_builder/src/QuickEditIntegration.php b/core/modules/layout_builder/src/QuickEditIntegration.php
new file mode 100644
index 0000000000..11a5379e59
--- /dev/null
+++ b/core/modules/layout_builder/src/QuickEditIntegration.php
@@ -0,0 +1,303 @@
+<?php
+
+namespace Drupal\layout_builder;
+
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Cache\CacheableMetadata;
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\FieldableEntityInterface;
+use Drupal\Core\Logger\LoggerChannelTrait;
+use Drupal\Core\Plugin\Context\Context;
+use Drupal\Core\Plugin\Context\ContextDefinition;
+use Drupal\Core\Plugin\Context\EntityContext;
+use Drupal\Core\Render\Element;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Helper methods for QuickEdit module integration.
+ *
+ * @internal
+ */
+class QuickEditIntegration implements ContainerInjectionInterface {
+
+  use LoggerChannelTrait;
+
+  /**
+   * The section storage manager.
+   *
+   * @var \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface
+   */
+  protected $sectionStorageManager;
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $currentUser;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a new QuickEditIntegration object.
+   *
+   * @param \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface $section_storage_manager
+   *   The section storage manager.
+   * @param \Drupal\Core\Session\AccountInterface $current_user
+   *   The current user.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(SectionStorageManagerInterface $section_storage_manager, AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager) {
+    $this->sectionStorageManager = $section_storage_manager;
+    $this->currentUser = $current_user;
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('plugin.manager.layout_builder.section_storage'),
+      $container->get('current_user'),
+      $container->get('entity_type.manager')
+    );
+  }
+
+  /**
+   * Alters the entity view build for Quick Edit compatibility.
+   *
+   * When rendering fields outside of normal view modes, Quick Edit requires
+   * that modules identify themselves with a view mode in the format
+   * [module_name]-[id].
+   *
+   * @param array $build
+   *   The built entity render array.
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
+   * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
+   *   The entity view display.
+   *
+   * @see hook_quickedit_render_field()
+   * @see layout_builder_quickedit_render_field()
+   *
+   * @internal
+   */
+  public function entityViewAlter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
+    if (!$entity instanceof FieldableEntityInterface || !isset($build['_layout_builder']) || !$this->currentUser->hasPermission('access in-place editing')) {
+      return;
+    }
+
+    $cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
+    $section_list = $this->sectionStorageManager->findByContext(
+      [
+        'display' => EntityContext::fromEntity($display),
+        'entity' => EntityContext::fromEntity($entity),
+        'view_mode' => new Context(new ContextDefinition('string'), $display->getMode()),
+      ],
+      $cacheable_metadata
+    );
+    $cacheable_metadata->applyTo($build);
+
+    if (empty($section_list)) {
+      return;
+    }
+
+    // Create a hash of the sections and use it in the unique Quick Edit ID.
+    // Any changes to the sections will result in a different hash, forcing
+    // Quick Edit to recognize any changes.
+    $sections_hash = hash('sha256', serialize($section_list->getSections()));
+
+    // Track each component by their plugin ID, delta, region, and UUID.
+    $plugin_ids_to_update = [];
+    foreach (Element::children($build['_layout_builder']) as $delta) {
+      $section = $build['_layout_builder'][$delta];
+      /** @var \Drupal\Core\Layout\LayoutDefinition $layout */
+      $layout = $section['#layout'];
+      $regions = $layout->getRegionNames();
+
+      foreach ($regions as $region) {
+        if (isset($section[$region])) {
+          foreach ($section[$region] as $uuid => $component) {
+            if (isset($component['#plugin_id']) && $this->supportQuickEditOnComponent($component, $entity)) {
+              $plugin_ids_to_update[$component['#plugin_id']][$delta][$region][$uuid] = $uuid;
+            }
+          }
+        }
+      }
+    }
+
+    // @todo Remove when https://www.drupal.org/node/3041850 is resolved.
+    $plugin_ids_to_update = array_filter($plugin_ids_to_update, function ($info) {
+      // Delta, region, and UUID each count as one.
+      return count($info, COUNT_RECURSIVE) === 3;
+    });
+
+    $plugin_ids_to_update = NestedArray::mergeDeepArray($plugin_ids_to_update, TRUE);
+    foreach ($plugin_ids_to_update as $delta => $regions) {
+      foreach ($regions as $region => $uuids) {
+        foreach ($uuids as $uuid => $component) {
+          $build['_layout_builder'][$delta][$region][$uuid]['content']['#view_mode'] = static::getViewModeId($entity, $display, $delta, $uuid, $sections_hash);
+        }
+      }
+    }
+  }
+
+  /**
+   * Generate a unique view mode ID.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
+   * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
+   *   The entity view display.
+   * @param int $delta
+   *   The delta.
+   * @param string $component_uuid
+   *   The component UUID.
+   * @param string $sections_hash
+   *   The hash of the sections.
+   *
+   * @return string
+   *   The unique view mode ID.
+   *
+   * @see \Drupal\layout_builder\QuickEditIntegration::deconstructViewModeId()
+   */
+  private static function getViewModeId(EntityInterface $entity, EntityViewDisplayInterface $display, $delta, $component_uuid, $sections_hash) {
+    return implode('-', [
+      'layout_builder',
+      $display->getMode(),
+      $delta,
+      // Replace the dashes in the component UUID because we need to
+      // use dashes to join the parts.
+      str_replace('-', '_', $component_uuid),
+      $entity->id(),
+      $sections_hash,
+    ]);
+  }
+
+  /**
+   * Deconstructs the view mode ID into its constituent parts.
+   *
+   * @param string $view_mode_id
+   *   The view mode ID.
+   *
+   * @return array
+   *   An array containing the entity view mode ID, the delta, the component
+   *   UUID, and the entity ID.
+   *
+   * @see \Drupal\layout_builder\QuickEditIntegration::getViewModeId()
+   */
+  private static function deconstructViewModeId($view_mode_id) {
+    list(, $entity_view_mode, $delta, $component_uuid, $entity_id) = explode('-', $view_mode_id, 7);
+    return [
+      $entity_view_mode,
+      // @todo Explicitly cast delta to an integer, remove this in
+      //   https://www.drupal.org/project/drupal/issues/2984509.
+      (int) $delta,
+      // Replace the underscores with dash to get back the component UUID.
+      str_replace('_', '-', $component_uuid),
+      $entity_id,
+    ];
+  }
+
+  /**
+   * Re-renders a field rendered by Layout Builder, edited with Quick Edit.
+   *
+   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
+   *   The entity.
+   * @param string $field_name
+   *   The field name.
+   * @param string $view_mode_id
+   *   The view mode ID.
+   * @param string $langcode
+   *   The language code.
+   *
+   * @return array
+   *   The re-rendered field.
+   *
+   * @internal
+   */
+  public function quickEditRenderField(FieldableEntityInterface $entity, $field_name, $view_mode_id, $langcode) {
+    list($entity_view_mode, $delta, $component_uuid) = static::deconstructViewModeId($view_mode_id);
+
+    $entity_build = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId())->view($entity, $entity_view_mode, $langcode);
+    $this->buildEntityView($entity_build);
+
+    if (isset($entity_build['_layout_builder'][$delta])) {
+      foreach (Element::children($entity_build['_layout_builder'][$delta]) as $region) {
+        if (isset($entity_build['_layout_builder'][$delta][$region][$component_uuid])) {
+          return $entity_build['_layout_builder'][$delta][$region][$component_uuid]['content'];
+        }
+      }
+    }
+
+    $this->getLogger('layout_builder')->warning('The field "%field" failed to render.', ['%field' => $field_name]);
+    return [];
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @todo Replace this hardcoded processing when
+   *   https://www.drupal.org/project/drupal/issues/3041635 is resolved.
+   *
+   * @see \Drupal\Tests\EntityViewTrait::buildEntityView()
+   */
+  private function buildEntityView(array &$elements) {
+    // If the default values for this element have not been loaded yet,
+    // populate them.
+    if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {
+      $elements += \Drupal::service('element_info')->getInfo($elements['#type']);
+    }
+
+    // Make any final changes to the element before it is rendered. This means
+    // that the $element or the children can be altered or corrected before
+    // the element is rendered into the final text.
+    if (isset($elements['#pre_render'])) {
+      foreach ($elements['#pre_render'] as $callable) {
+        $elements = call_user_func($callable, $elements);
+      }
+    }
+
+    // And recurse.
+    $children = Element::children($elements, TRUE);
+    foreach ($children as $key) {
+      $this->buildEntityView($elements[$key]);
+    }
+  }
+
+  /**
+   * Determines whether a component has QuickEdit support.
+   *
+   * Only field_block components for view configurable fields should be
+   * supported.
+   *
+   * @param array $component
+   *   The component render array.
+   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
+   *   The entity being displayed.
+   *
+   * @return bool
+   *   Whether QuickEdit is supported on the component.
+   *
+   * @see \Drupal\layout_builder\Plugin\Block\FieldBlock
+   */
+  private function supportQuickEditOnComponent(array $component, FieldableEntityInterface $entity) {
+    if (isset($component['content']['#field_name'], $component['#base_plugin_id']) && $component['#base_plugin_id'] === 'field_block') {
+      return $entity->getFieldDefinition($component['content']['#field_name'])->isDisplayConfigurable('view');
+    }
+    return FALSE;
+  }
+
+}
diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderQuickEditTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderQuickEditTest.php
new file mode 100644
index 0000000000..84f50ece44
--- /dev/null
+++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderQuickEditTest.php
@@ -0,0 +1,404 @@
+<?php
+
+namespace Drupal\Tests\layout_builder\FunctionalJavascript;
+
+use Drupal\Core\Entity\Entity\EntityViewDisplay;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\node\Entity\NodeType;
+use Drupal\node\NodeInterface;
+use Drupal\Tests\quickedit\FunctionalJavascript\QuickEditIntegrationTest;
+
+/**
+ * Tests that Layout Builder functions with Quick Edit.
+ *
+ * @covers layout_builder_entity_view_alter()
+ * @covers layout_builder_quickedit_render_field()
+ *
+ * @group layout_builder
+ */
+class LayoutBuilderQuickEditTest extends QuickEditIntegrationTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'layout_builder',
+    'layout_builder_test_css_transitions',
+    'datetime',
+  ];
+
+  /**
+   * Whether the test is currently using Layout Builder on the entity.
+   *
+   * Allows performing assertions with and without Layout Builder.
+   *
+   * @var bool
+   *
+   * @see ::assertEntityInstanceFieldStates()
+   * @see ::assertEntityInstanceFieldMarkup()
+   */
+  protected $usingLayoutBuilder = FALSE;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    // @todo The Layout Builder UI relies on local tasks; fix in
+    //   https://www.drupal.org/project/drupal/issues/2917777.
+    $this->drupalPlaceBlock('local_tasks_block');
+
+    $field_storage = FieldStorageConfig::create([
+      'field_name' => 'field_date',
+      'entity_type' => 'node',
+      'type' => 'datetime',
+    ]);
+    $field_storage->save();
+    $field = FieldConfig::create([
+      'field_storage' => $field_storage,
+      'bundle' => 'article',
+      'label' => 'Date field',
+    ]);
+    $field->save();
+
+    // Save the current user to re-login after Layout Builder changes.
+    $user = $this->loggedInUser;
+    $this->loginLayoutAdmin();
+
+    $page = $this->getSession()->getPage();
+
+    $this->drupalGet('admin/structure/block/block-content/manage/basic/display');
+    $page->checkField('layout[enabled]');
+    $page->pressButton('Save');
+
+    $this->drupalLogin($user);
+  }
+
+  /**
+   * Tests enabling and displaying Layout Builder on a node.
+   *
+   * @param bool $use_revisions
+   *   If revisions are used.
+   *
+   * @dataProvider providerEnableDisableLayoutBuilder
+   */
+  public function testEnableDisableLayoutBuilder($use_revisions) {
+    if (!$use_revisions) {
+      $content_type = NodeType::load('article');
+      $content_type->setNewRevision(FALSE);
+      $content_type->save();
+    }
+    $node = $this->createNodeWithTerm();
+
+    $this->assertQuickEditInit($node);
+    $this->enableLayouts('admin/structure/types/manage/article/display/default');
+    $this->usingLayoutBuilder = TRUE;
+    // Test article with Layout Builder enabled.
+    $this->assertQuickEditInit($node);
+
+    // Test article with Layout Builder override.
+    $this->createLayoutOverride('node/' . $node->id() . '/layout');
+    $this->assertQuickEditInit($node);
+
+    // If we are not using revisions remove the layout override and disable
+    // layout for the bundle.
+    if (!$use_revisions) {
+      // Test article with Layout Builder when reverted back to defaults.
+      $this->revertLayoutToDefaults('node/' . $node->id() . '/layout');
+      $this->assertQuickEditInit($node);
+
+      // Test with Layout Builder disabled after being enabled.
+      $this->usingLayoutBuilder = FALSE;
+      $this->disableLayoutBuilder('admin/structure/types/manage/article/display/default');
+      $this->assertQuickEditInit($node);
+    }
+  }
+
+  /**
+   * DataProvider for testEnableDisableLayoutBuilder().
+   */
+  public function providerEnableDisableLayoutBuilder() {
+    return [
+      'use revisions' => [TRUE],
+      'do not use revisions' => [FALSE],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param bool $useOverride
+   *   Whether test should use a layout override.
+   *
+   * @dataProvider provideTestArticleNode
+   */
+  public function testArticleNode($useOverride = FALSE) {
+    $this->enableLayouts('admin/structure/types/manage/article/display/default');
+    $this->usingLayoutBuilder = TRUE;
+    $node = $this->createNodeWithTerm();
+    if ($useOverride) {
+      $this->createLayoutOverride('node/' . $node->id() . '/layout');
+    }
+    $this->doTestArticle($node);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function testCustomBlock() {
+    $this->usingLayoutBuilder = TRUE;
+    parent::testCustomBlock();
+  }
+
+  /**
+   * Enables layouts at an admin path.
+   *
+   * @param string $path
+   *   The manage display path.
+   */
+  protected function enableLayouts($path) {
+    // Save the current user to re-login after Layout Builder changes.
+    $user = $this->loggedInUser;
+    $this->loginLayoutAdmin();
+    $page = $this->getSession()->getPage();
+    $this->drupalGet($path);
+    $page->checkField('layout[enabled]');
+    $page->checkField('layout[allow_custom]');
+    $page->pressButton('Save');
+    $this->drupalLogin($user);
+  }
+
+  /**
+   * Data provider for testArticleNode().
+   */
+  public function provideTestArticleNode() {
+    return [
+      'no override' => [FALSE],
+      'use override' => [TRUE],
+    ];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function assertEntityInstanceFieldStates($entity_type_id, $entity_id, $entity_instance_id, array $expected_field_states) {
+    if ($this->usingLayoutBuilder) {
+      $expected_field_states = $this->replaceLayoutBuilderFieldIdKeys($expected_field_states);
+    }
+    parent::assertEntityInstanceFieldStates($entity_type_id, $entity_id, $entity_instance_id, $expected_field_states);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function assertEntityInstanceFieldMarkup($entity_type_id, $entity_id, $entity_instance_id, array $expected_field_attributes) {
+    if ($this->usingLayoutBuilder) {
+      $expected_field_attributes = $this->replaceLayoutBuilderFieldIdKeys($expected_field_attributes);
+    }
+    parent::assertEntityInstanceFieldMarkup($entity_type_id, $entity_id, $entity_instance_id, $expected_field_attributes);
+  }
+
+  /**
+   * Replaces the keys in the array with field IDs used for Layout Builder.
+   *
+   * @param array $array
+   *   The array with field IDs as keys.
+   *
+   * @return array
+   *   The array with the keys replaced.
+   */
+  protected function replaceLayoutBuilderFieldIdKeys(array $array) {
+    $replacement = [];
+    foreach ($array as $field_key => $value) {
+      $new_field_key = $this->getQuickEditFieldId($field_key);
+      $replacement[$new_field_key] = $value;
+    }
+    return $replacement;
+  }
+
+  /**
+   * Gets view mode that Layout Builder used for a field.
+   *
+   * @param string $entity_type
+   *   The entity type.
+   * @param int $entity_id
+   *   The entity ID.
+   * @param string $field_name
+   *   The field name.
+   * @param string $view_mode
+   *   The view mode.
+   *
+   * @return string
+   *   The view mode used by Layout Builder.
+   */
+  protected function getLayoutBuilderViewMode($entity_type, $entity_id, $field_name, $view_mode) {
+    // If the field is one that is not rendered by Layout Builder do not change
+    // $view_mode.
+    if (in_array($field_name, ['title', 'uid', 'created'])) {
+      return $view_mode;
+    }
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
+    $entity = $this->container->get('entity_type.manager')->getStorage($entity_type)->load($entity_id);
+    $view_display = EntityViewDisplay::collectRenderDisplay($entity, 'default');
+    $sections = $view_display->getSections();
+    // Find the component with the plugin ID in the field_block format that
+    // matches the entity type, bundle, and field name.
+    foreach (reset($sections)->getComponents() as $component) {
+      $component_in_view_mode = str_replace('-', '_', $component->getUuid());
+      if ($component->getPlugin()->getPluginId() === "field_block:$entity_type:{$entity->bundle()}:$field_name") {
+        return 'layout_builder-0-' . $component_in_view_mode . '-' . $entity->id();
+      }
+    }
+    $this->fail("Component not found for: $entity_type, $entity_id, $field_name");
+  }
+
+  /**
+   * Login the Layout admin user for the test.
+   */
+  protected function loginLayoutAdmin() {
+    // Enable for the Layout Builder.
+    $this->drupalLogin($this->drupalCreateUser([
+      'configure any layout',
+      'access content',
+      'administer node display',
+      'administer node fields',
+      'administer block_content display',
+      'administer block_content fields',
+      'administer blocks',
+    ]));
+  }
+
+  /**
+   * Creates a layout override.
+   *
+   * @param string $layout_url
+   *   The Layout Builder URL.
+   */
+  protected function createLayoutOverride($layout_url) {
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+
+    // Save the current user to re-login after Layout Builder changes.
+    $user = $this->loggedInUser;
+    $this->loginLayoutAdmin();
+    $this->drupalGet($layout_url);
+
+    $page->clickLink('Add Block');
+    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas'));
+    $assert_session->assertWaitOnAjaxRequest();
+
+    $page->clickLink('Date field');
+    $assert_session->assertWaitOnAjaxRequest();
+    $page->pressButton('Add Block');
+    $assert_session->assertWaitOnAjaxRequest();
+
+    $page->clickLink('Add Block');
+    $this->assertNotEmpty($assert_session->waitForElementVisible('css', '#drupal-off-canvas'));
+    $assert_session->assertWaitOnAjaxRequest();
+
+    $page->clickLink('Date field');
+    $assert_session->assertWaitOnAjaxRequest();
+    $page->pressButton('Add Block');
+    $assert_session->assertWaitOnAjaxRequest();
+
+    $page->pressButton('Save layout');
+    $this->assertNotEmpty($assert_session->waitForElement('css', '.messages--status'));
+    $assert_session->pageTextContains('The layout override has been saved.');
+    $this->drupalLogin($user);
+  }
+
+  /**
+   * Reverts a layout override.
+   *
+   * @param string $layout_url
+   *   The Layout Builder URL.
+   */
+  protected function revertLayoutToDefaults($layout_url) {
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+    // Save the current user to re-login after Layout Builder changes.
+    $user = $this->loggedInUser;
+    $this->loginLayoutAdmin();
+    $this->drupalGet($layout_url);
+    $assert_session->buttonExists('Revert to defaults');
+    $page->pressButton('Revert to defaults');
+    $page->pressButton('Revert');
+    $assert_session->pageTextContains('The layout has been reverted back to defaults.');
+    $this->drupalLogin($user);
+  }
+
+  /**
+   * Disable Layout Builder.
+   *
+   * @param string $path
+   *   The path to the manage display page.
+   */
+  protected function disableLayoutBuilder($path) {
+    $page = $this->getSession()->getPage();
+    // Save the current user to re-login after Layout Builder changes.
+    $user = $this->loggedInUser;
+    $this->loginLayoutAdmin();
+    $this->drupalGet($path);
+    $page->uncheckField('layout[allow_custom]');
+    $page->uncheckField('layout[enabled]');
+    $page->pressButton('Save');
+    $page->pressButton('Confirm');
+    $this->drupalLogin($user);
+  }
+
+  /**
+   * Asserts that QuickEdit is initialized on the node view correctly.
+   *
+   * @todo Replace calls to this method with calls to ::doTestArticle() in
+   *    https://www.drupal.org/node/3037436.
+   *
+   * @param \Drupal\node\NodeInterface $node
+   *   The node.
+   */
+  private function assertQuickEditInit(NodeInterface $node) {
+    $this->drupalGet('node/' . $node->id());
+
+    // Initial state.
+    $this->awaitQuickEditForEntity('node', 1);
+    $this->assertEntityInstanceStates([
+      'node/1[0]' => 'closed',
+    ]);
+    $this->assertEntityInstanceFieldStates('node', 1, 0, [
+      'node/1/title/en/full'      => 'inactive',
+      'node/1/uid/en/full'        => 'inactive',
+      'node/1/created/en/full'    => 'inactive',
+      'node/1/body/en/full'       => 'inactive',
+      'node/1/field_tags/en/full' => 'inactive',
+    ]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getQuickEditFieldId($original_field_id) {
+    $page = $this->getSession()->getPage();
+    $parts = explode('/', $original_field_id);
+    // Remove the last part of the field id which will contain the QuickEdit
+    // view_mode. When using the Layout Builder the view_mode will contain a
+    // hash of the layout sections and will be different each time the layout
+    // changes.
+    array_pop($parts);
+    $field_key_without_view_mode = implode('/', $parts);
+    $element = $page->find('css', "[data-quickedit-field-id^=\"$field_key_without_view_mode\"]");
+    $this->assertNotEmpty($element, "Found QuickEdit element starting with: $field_key_without_view_mode");
+    return $element->getAttribute('data-quickedit-field-id');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function createNodeWithTerm() {
+    $node = parent::createNodeWithTerm();
+    $node->field_date = '1978-11-19T05:00:00';
+    $node->save();
+    return $node;
+  }
+
+}
diff --git a/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php b/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php
index 52d645f0f8..b617167740 100644
--- a/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php
+++ b/core/modules/quickedit/tests/src/FunctionalJavascript/QuickEditIntegrationTest.php
@@ -7,6 +7,7 @@
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\editor\Entity\Editor;
 use Drupal\filter\Entity\FilterFormat;
+use Drupal\node\NodeInterface;
 use Drupal\taxonomy\Entity\Term;
 use Drupal\taxonomy\Entity\Vocabulary;
 use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
@@ -92,6 +93,14 @@ protected function setUp() {
       ->setComponent($field_name, ['type' => 'entity_reference_label'])
       ->save();
 
+    $block_content_type = BlockContentType::create([
+      'id' => 'basic',
+      'label' => 'basic',
+      'revision' => FALSE,
+    ]);
+    $block_content_type->save();
+    block_content_add_body_field($block_content_type->id());
+
     $this->drupalPlaceBlock('page_title_block');
     $this->drupalPlaceBlock('system_main_block');
 
@@ -114,24 +123,17 @@ protected function setUp() {
    * Tests if an article node can be in-place edited with Quick Edit.
    */
   public function testArticleNode() {
-    $term = Term::create([
-      'name' => 'foo',
-      'vid' => 'tags',
-    ]);
-    $term->save();
-
-    $node = $this->drupalCreateNode([
-      'type' => 'article',
-      'title' => t('My Test Node'),
-      'body' => [
-        'value' => '<p>Hello world!</p><p>I do not know what to say…</p><p>I wish I were eloquent.</p>',
-        'format' => 'some_format',
-      ],
-      'field_tags' => [
-        ['target_id' => $term->id()],
-      ],
-    ]);
+    $node = $this->createNodeWithTerm();
+    $this->doTestArticle($node);
+  }
 
+  /**
+   * Tests an article with QuickEdit.
+   *
+   * @param \Drupal\node\NodeInterface $node
+   *   The node.
+   */
+  protected function doTestArticle(NodeInterface $node) {
     $this->drupalGet('node/' . $node->id());
 
     // Initial state.
@@ -164,7 +166,7 @@ public function testArticleNode() {
     $assert_session = $this->assertSession();
 
     // Click the title field.
-    $this->click('[data-quickedit-field-id="node/1/title/en/full"].quickedit-candidate');
+    $this->click('[data-quickedit-field-id="' . $this->getQuickEditFieldId('node/1/title/en/full') . '"].quickedit-candidate');
     $assert_session->waitForElement('css', '.quickedit-toolbar-field div[id*="title"]');
     $this->assertQuickEditEntityToolbar((string) $node->label(), 'Title');
     $this->assertEntityInstanceFieldStates('node', 1, 0, [
@@ -179,7 +181,7 @@ public function testArticleNode() {
     ]);
 
     // Append something to the title.
-    $this->typeInPlainTextEditor('[data-quickedit-field-id="node/1/title/en/full"].quickedit-candidate', ' Llamas are awesome!');
+    $this->typeInPlainTextEditor('[data-quickedit-field-id="' . $this->getQuickEditFieldId('node/1/title/en/full') . '"].quickedit-candidate', ' Llamas are awesome!');
     $this->awaitEntityInstanceFieldState('node', 1, 0, 'title', 'en', 'changed');
     $this->assertEntityInstanceFieldStates('node', 1, 0, [
       'node/1/title/en/full'      => 'changed',
@@ -216,7 +218,7 @@ public function testArticleNode() {
 
     // Click the tags field.
     hold_test_response(TRUE);
-    $this->click('[data-quickedit-field-id="node/1/field_tags/en/full"]');
+    $this->click('[data-quickedit-field-id="' . $this->getQuickEditFieldId('node/1/field_tags/en/full') . '"]');
     $assert_session->waitForElement('css', '.quickedit-toolbar-field div[id*="tags"]');
     $this->assertQuickEditEntityToolbar((string) $node->label(), 'Tags');
     $this->assertEntityInstanceFieldStates('node', 1, 0, [
@@ -284,14 +286,6 @@ public function testArticleNode() {
    * Tests if a custom can be in-place edited with Quick Edit.
    */
   public function testCustomBlock() {
-    $block_content_type = BlockContentType::create([
-      'id' => 'basic',
-      'label' => 'basic',
-      'revision' => FALSE,
-    ]);
-    $block_content_type->save();
-    block_content_add_body_field($block_content_type->id());
-
     $block_content = BlockContent::create([
       'info' => 'Llama',
       'type' => 'basic',
@@ -340,4 +334,44 @@ public function testCustomBlock() {
     $this->assertSession()->elementExists('css', '#quickedit-entity-toolbar .quickedit-toolgroup.wysiwyg-main > .cke_chrome .cke_top[role="presentation"] .cke_toolbar[role="toolbar"] .cke_toolgroup[role="presentation"] > .cke_button[title~="Bold"][role="button"]');
   }
 
+  /**
+   * Create a node with a term reference for testing.
+   *
+   * @return \Drupal\node\NodeInterface
+   *   The created node.
+   */
+  protected function createNodeWithTerm() {
+    $term = Term::create([
+      'name' => 'foo',
+      'vid' => 'tags',
+    ]);
+    $term->save();
+
+    $node = $this->drupalCreateNode([
+      'type' => 'article',
+      'title' => t('My Test Node'),
+      'body' => [
+        'value' => '<p>Hello world!</p><p>I do not know what to say…</p><p>I wish I were eloquent.</p>',
+        'format' => 'some_format',
+      ],
+      'field_tags' => [
+        ['target_id' => $term->id()],
+      ],
+    ]);
+    return $node;
+  }
+
+  /**
+   * Gets the QuickEdit field ID attribute value.
+   *
+   * @param string $original_field_id
+   *   The original field ID.
+   *
+   * @return string
+   *   The current field ID.
+   */
+  protected function getQuickEditFieldId($original_field_id) {
+    return $original_field_id;
+  }
+
 }
