diff --git a/core/modules/system/templates/container.html.twig b/core/modules/system/templates/container.html.twig
index 167965c..0ba6544 100644
--- a/core/modules/system/templates/container.html.twig
+++ b/core/modules/system/templates/container.html.twig
@@ -17,6 +17,9 @@
  * @ingroup themeable
  */
 #}
+{% if title_suffix %}
+{{ title_suffix }}
+{% endif %}
 {%
   set classes = [
     has_parent ? 'js-form-wrapper',
diff --git a/core/modules/views/js/views-contextual.js b/core/modules/views/js/views-contextual.js
index e6586eb..befc621 100644
--- a/core/modules/views/js/views-contextual.js
+++ b/core/modules/views/js/views-contextual.js
@@ -17,7 +17,7 @@
    */
   Drupal.behaviors.viewsContextualLinks = {
     attach: function (context) {
-      var id = $('body').attr('data-views-page-contextual-id');
+      var id = $('div.contextual-region').attr('data-views-page-contextual-id');
 
       $('[data-contextual-id="' + id + '"]')
         .closest(':has(.view)')
diff --git a/core/modules/views/src/Plugin/views/display/Page.php b/core/modules/views/src/Plugin/views/display/Page.php
index 656105c..695697f 100644
--- a/core/modules/views/src/Plugin/views/display/Page.php
+++ b/core/modules/views/src/Plugin/views/display/Page.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\State\StateInterface;
 use Drupal\Core\Routing\RouteProviderInterface;
+use Drupal\Core\Template\AttributeArray;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -28,7 +29,6 @@
  *   help = @Translation("Display the view as a page, with a URL and menu links."),
  *   uses_menu_links = TRUE,
  *   uses_route = TRUE,
- *   contextual_links_locations = {"page"},
  *   theme = "views_view",
  *   admin = @Translation("Page")
  * )
@@ -537,4 +537,38 @@ public function calculateDependencies() {
     return $dependencies;
   }
 
+  /**
+   * #pre_render callback for view display rendering.
+   *
+   * @see self::render()
+   *
+   * @param array $element
+   *   The element to #pre_render
+   *
+   * @return array
+   *   The processed element.
+   */
+  public function elementPreRender(array $element) {
+    $element = parent::elementPreRender($element);
+
+    // If the page contains a view as its main content, contextual links may have
+    // been attached to the page as a whole; for example, by views_page_alter().
+    // This allows them to be associated with the page and rendered by default
+    // next to the page title (which we want). However, it also causes the
+    // Contextual Links module to treat the wrapper for the entire page (i.e.,
+    // the <body> tag) as the HTML element that these contextual links are
+    // associated with. This we don't want; for better visual highlighting, we
+    // prefer a smaller region to be chosen. The region we prefer differs from
+    // theme to theme and depends on the details of the theme's markup in
+    // page.html.twig, so we can only find it using JavaScript. We therefore
+    // remove the "contextual-region" class from the <body> tag here and add
+    // JavaScript that will insert it back in the correct place.
+    if (!empty($element['#views_contextual_links']) && !empty($element['#contextual_links']) && isset($element['#attributes']['class'])) {
+      $element['#attributes']['data-views-page-contextual-id'] = _contextual_links_to_id($element['#contextual_links']);
+      $element['#attached']['library'][] = 'views/views.contextual-links';
+    }
+
+    return $element;
+  }
+
 }
