diff --git a/core/modules/media/templates/media.html.twig b/core/modules/media/templates/media.html.twig
index 28c0a83ca64ed2cfa9d21c82447ca3faf2431ffa..6b3d6b3f0a42052180be6011454956c77607d111 100644
--- a/core/modules/media/templates/media.html.twig
+++ b/core/modules/media/templates/media.html.twig
@@ -26,11 +26,16 @@
* - title_attributes: Same as attributes, except applied to the main title
* tag that appears in the template.
*
+ * Note that we print {{ title_suffix }} even though the title is not included.
+ * This is intentional, once contextual links are embedded in the "title_suffix"
+ * variable. See #2775131 for more information on the background about this.
+ *
* @see template_preprocess_media()
*
* @ingroup themeable
*/
#}
+ {{ title_suffix }}
{{ content }}
diff --git a/core/modules/media/tests/src/Functional/MediaContextualLinksTest.php b/core/modules/media/tests/src/Functional/MediaContextualLinksTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..1d97773143ac8fa943f0125bf77c2782e3cd3fd9
--- /dev/null
+++ b/core/modules/media/tests/src/Functional/MediaContextualLinksTest.php
@@ -0,0 +1,45 @@
+createMediaType();
+
+ // Create a media item.
+ $media = Media::create([
+ 'bundle' => $mediaType->id(),
+ 'name' => 'Unnamed',
+ ]);
+ $media->save();
+
+ $user = $this->drupalCreateUser([
+ 'administer media',
+ 'access contextual links',
+ ]);
+ $this->drupalLogin($user);
+
+ $this->drupalGet('media/' . $media->id());
+ $this->assertSession()->elementAttributeContains('css', 'div[data-contextual-id]', 'data-contextual-id', 'media:media=' . $media->id() . ':');
+ }
+
+}
diff --git a/core/themes/classy/templates/content/media.html.twig b/core/themes/classy/templates/content/media.html.twig
index f36975cb9a37a52fc756c68b11ab2125344586c3..6728367c0be2cd9ce98954a4599e91b06c41d3e2 100644
--- a/core/themes/classy/templates/content/media.html.twig
+++ b/core/themes/classy/templates/content/media.html.twig
@@ -7,6 +7,10 @@
* - name: Name of the media.
* - content: Media content.
*
+ * Note that we print {{ title_suffix }} even though the title is not included.
+ * This is intentional, once contextual links are embedded in the "title_suffix"
+ * variable. See #2775131 for more information on the background about this.
+ *
* @see template_preprocess_media()
*
* @ingroup themeable
@@ -21,6 +25,7 @@
]
%}
+ {{ title_suffix }}
{% if content %}
{{ content }}
{% endif %}
diff --git a/core/themes/stable/templates/content/media.html.twig b/core/themes/stable/templates/content/media.html.twig
index 769b7be751aa309a0a57c52fa0b4e48bcc828ba8..cecaac8b198a718bed90c5109d2bd4e441a498cc 100644
--- a/core/themes/stable/templates/content/media.html.twig
+++ b/core/themes/stable/templates/content/media.html.twig
@@ -7,12 +7,17 @@
* - name: Name of the media.
* - content: Media content.
*
+ * Note that we print {{ title_suffix }} even though the title is not included.
+ * This is intentional, once contextual links are embedded in the "title_suffix"
+ * variable. See #2775131 for more information on the background about this.
+ *
* @see template_preprocess_media()
*
* @ingroup themeable
*/
#}
+ {{ title_suffix }}
{% if content %}
{{ content }}
{% endif %}