diff --git a/core/lib/Drupal/Core/Layout/Annotation/Layout.php b/core/lib/Drupal/Core/Layout/Annotation/Layout.php
index 1cb5ff0..3226a28 100644
--- a/core/lib/Drupal/Core/Layout/Annotation/Layout.php
+++ b/core/lib/Drupal/Core/Layout/Annotation/Layout.php
@@ -59,6 +59,18 @@ class Layout extends Plugin {
   public $description;
 
   /**
+   * An array of types this layout is suitable for.
+   *
+   * Available options:
+   * - page
+   * - content
+   * - partial
+   *
+   * @var string[] optional
+   */
+  public $types = [];
+
+  /**
    * The human-readable category.
    *
    * @var string
diff --git a/core/lib/Drupal/Core/Layout/LayoutDefinition.php b/core/lib/Drupal/Core/Layout/LayoutDefinition.php
index 9fab205..db58371 100644
--- a/core/lib/Drupal/Core/Layout/LayoutDefinition.php
+++ b/core/lib/Drupal/Core/Layout/LayoutDefinition.php
@@ -61,6 +61,15 @@ class LayoutDefinition implements PluginDefinitionInterface, DerivablePluginDefi
   protected $description;
 
   /**
+   * An array of types this layout is suitable for.
+   *
+   * @see \Drupal\Core\Layout\Annotation\Layout::$types
+   *
+   * @var string[]
+   */
+  protected $types;
+
+  /**
    * The human-readable category.
    *
    * @var string
@@ -267,6 +276,40 @@ public function setDescription($description) {
   }
 
   /**
+   * Returns the types this layout is suitable for.
+   *
+   * @return string[]
+   *   An array of type strings, see
+   *   \Drupal\Core\Layout\Annotation\Layout::$types for common types.
+   */
+  public function getTypes() {
+    return $this->types;
+  }
+
+  /**
+   * Determines if this layout matches the specified type.
+   *
+   * @param string $type
+   *   The layout type to match.
+   *
+   * @return bool
+   *   TRUE if this layout matches the specified type, FALSE otherwise.
+   */
+  public function hasType($type) {
+    return array_search($type, $this->types, TRUE) !== FALSE;
+  }
+
+  /**
+   * @param string[] $types
+   *
+   * @return $this
+   */
+  public function setTypes(array $types) {
+    $this->types = $types;
+    return $this;
+  }
+
+  /**
    * Gets the human-readable category of the layout definition.
    *
    * @return string|\Drupal\Core\StringTranslation\TranslatableMarkup
diff --git a/core/lib/Drupal/Core/Layout/LayoutPluginManager.php b/core/lib/Drupal/Core/Layout/LayoutPluginManager.php
index 8ff11eb..1ce9ba6 100644
--- a/core/lib/Drupal/Core/Layout/LayoutPluginManager.php
+++ b/core/lib/Drupal/Core/Layout/LayoutPluginManager.php
@@ -212,9 +212,9 @@ public function getGroupedDefinitions(array $definitions = NULL, $label_key = 'l
   /**
    * {@inheritdoc}
    */
-  public function getLayoutOptions() {
+  public function getLayoutOptions(array $definitions = NULL) {
     $layout_options = [];
-    foreach ($this->getGroupedDefinitions() as $category => $layout_definitions) {
+    foreach ($this->getGroupedDefinitions($definitions) as $category => $layout_definitions) {
       foreach ($layout_definitions as $name => $layout_definition) {
         $layout_options[$category][$name] = $layout_definition->getLabel();
       }
@@ -222,4 +222,23 @@ public function getLayoutOptions() {
     return $layout_options;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefinitionsForType($type, $include_empty_type = FALSE, $negate = FALSE) {
+    return array_filter($this->getDefinitions(), function (LayoutDefinition $definition) use ($type, $include_empty_type, $negate) {
+      $definition_types = $definition->getTypes();
+
+      // If the definition does not specify a type, let the $include_empty_types
+      // parameter decide if it is valid.
+      if (empty($definition_types)) {
+        return $include_empty_type;
+      }
+
+      // Determine if the type is present and apply $negate to the result.
+      $valid_type = $definition->hasType($type);
+      return $valid_type xor $negate;
+    });
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Layout/LayoutPluginManagerInterface.php b/core/lib/Drupal/Core/Layout/LayoutPluginManagerInterface.php
index df15be0..8916757 100644
--- a/core/lib/Drupal/Core/Layout/LayoutPluginManagerInterface.php
+++ b/core/lib/Drupal/Core/Layout/LayoutPluginManagerInterface.php
@@ -62,9 +62,29 @@ public function getGroupedDefinitions(array $definitions = NULL);
   /**
    * Returns an array of layout labels grouped by category.
    *
+   * @param array[]|null $definitions
+   *   (optional) The plugin definitions to group. If omitted, all plugin
+   *   definitions are used.
+   *
    * @return string[][]
    *   A nested array of labels suitable for #options.
    */
-  public function getLayoutOptions();
+  public function getLayoutOptions(array $definitions = NULL);
+
+  /**
+   * Gets the definitions of all layouts that match the specified type.
+   *
+   * @param string $type
+   *   The layout type to match.
+   * @param bool $include_empty_type
+   *   (optional) If TRUE, any layouts that do not specify any type will be
+   *   included. Defaults to FALSE.
+   * @param bool $negate
+   *   (optional) If TRUE, the $type will be excluded from the results. Defaults
+   *   to FALSE.
+   *
+   * @return \Drupal\Core\Layout\LayoutDefinition[][]
+   */
+  public function getDefinitionsForType($type, $include_empty_type = FALSE, $negate = FALSE);
 
 }
diff --git a/core/modules/field_layout/src/Form/FieldLayoutEntityDisplayFormTrait.php b/core/modules/field_layout/src/Form/FieldLayoutEntityDisplayFormTrait.php
index 4f6b52e..733309b 100644
--- a/core/modules/field_layout/src/Form/FieldLayoutEntityDisplayFormTrait.php
+++ b/core/modules/field_layout/src/Form/FieldLayoutEntityDisplayFormTrait.php
@@ -57,7 +57,7 @@ public function form(array $form, FormStateInterface $form_state) {
     $form['field_layouts']['field_layout'] = [
       '#type' => 'select',
       '#title' => $this->t('Select a layout'),
-      '#options' => $this->layoutPluginManager->getLayoutOptions(),
+      '#options' => $this->layoutPluginManager->getLayoutOptions($this->layoutPluginManager->getDefinitionsForType('content', TRUE)),
       '#default_value' => $layout_plugin->getPluginId(),
       '#ajax' => [
         'callback' => '::settingsAjax',
diff --git a/core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php b/core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php
index d892b47..a9919dd 100644
--- a/core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Layout/LayoutPluginManagerTest.php
@@ -277,6 +277,73 @@ public function testGetGroupedDefinitions() {
   }
 
   /**
+   * @covers ::getDefinitionsForType
+   * @covers \Drupal\Core\Layout\LayoutDefinition::hasType
+   *
+   * @dataProvider providerTestGetDefinitionsForType
+   */
+  public function testGetDefinitionsForType($type, $include_empty_type, $negate, $expected) {
+    $actual = $this->layoutPluginManager->getDefinitionsForType($type, $include_empty_type, $negate);
+    $this->assertArrayEquals($expected, array_keys($actual));
+  }
+
+  /**
+   * Provides test data to ::testGetDefinitionsForType().
+   */
+  public function providerTestGetDefinitionsForType() {
+    $data = [];
+    $data['match_include_empty_type_negate'] = [
+      'partial',
+      TRUE,
+      TRUE,
+      ['theme_a_provided_layout', 'plugin_provided_layout'],
+    ];
+    $data['match_negate'] = [
+      'partial',
+      FALSE,
+      TRUE,
+      ['theme_a_provided_layout'],
+    ];
+    $data['match_include_empty_type'] = [
+      'partial',
+      TRUE,
+      FALSE,
+      ['module_a_provided_layout', 'plugin_provided_layout'],
+    ];
+    $data['match'] = [
+      'partial',
+      FALSE,
+      FALSE,
+      ['module_a_provided_layout'],
+    ];
+    $data['no_match_include_empty_type_negate'] = [
+      'invalid',
+      TRUE,
+      TRUE,
+      ['module_a_provided_layout', 'theme_a_provided_layout', 'plugin_provided_layout'],
+    ];
+    $data['no_match_negate'] = [
+      'invalid',
+      FALSE,
+      TRUE,
+      ['module_a_provided_layout', 'theme_a_provided_layout'],
+    ];
+    $data['no_match_include_empty_type'] = [
+      'invalid',
+      TRUE,
+      FALSE,
+      ['plugin_provided_layout'],
+    ];
+    $data['no_match'] = [
+      'invalid',
+      FALSE,
+      FALSE,
+      [],
+    ];
+    return $data;
+  }
+
+  /**
    * Sets up the filesystem with YAML files and annotated plugins.
    */
   protected function setUpFilesystem() {
@@ -284,6 +351,8 @@ protected function setUpFilesystem() {
 module_a_provided_layout:
   label: 1 column layout
   category: 'Columns: 1'
+  types:
+    - partial
   theme_hook: onecol
   path: layouts
   library: module_a/onecol
@@ -301,6 +370,8 @@ protected function setUpFilesystem() {
   class: '\Drupal\Core\Layout\LayoutDefault'
   label: 2 column layout
   category: 'Columns: 2'
+  types:
+    - page
   template: twocol
   path: templates
   library: theme_a/twocol
