diff --git a/core/modules/system/templates/container.html.twig b/core/modules/system/templates/container.html.twig
index 6fb8159..ca47484 100644
--- a/core/modules/system/templates/container.html.twig
+++ b/core/modules/system/templates/container.html.twig
@@ -17,4 +17,7 @@
  * @ingroup themeable
  */
 #}
+{% if title_suffix %}
+{{ title_suffix }}
+{% endif %}
 <div{{ attributes.addClass(has_parent ? 'form-wrapper') }}>{{ children }}</div>
diff --git a/core/modules/views/js/views-contextual.js b/core/modules/views/js/views-contextual.js
index e5eb14b..2442ad2 100644
--- a/core/modules/views/js/views-contextual.js
+++ b/core/modules/views/js/views-contextual.js
@@ -8,7 +8,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 bdbf54a..1ccac5e 100644
--- a/core/modules/views/src/Plugin/views/display/Page.php
+++ b/core/modules/views/src/Plugin/views/display/Page.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Template\AttributeArray;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
@@ -23,7 +24,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")
  * )
@@ -441,4 +441,38 @@ public function getPagerText() {
     );
   }
 
+  /**
+   * #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;
+  }
+
 }
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index a41e73e..5fc44f8 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -285,18 +285,6 @@ function views_theme_suggestions_comment_alter(array &$suggestions, array $varia
 }
 
 /**
- * Implements hook_page_alter().
- */
-function views_page_alter(&$page) {
-  // If the main content of this page contains a view, attach its contextual
-  // links to the overall page array. This allows them to be rendered directly
-  // next to the page title.
-  if ($view = views_get_page_view()) {
-    views_add_contextual_links($page, 'page', $view, $view->current_display);
-  }
-}
-
-/**
  * Implements MODULE_preprocess_HOOK().
  */
 function views_preprocess_page(&$variables) {
@@ -305,33 +293,6 @@ function views_preprocess_page(&$variables) {
     return;
   }
 
-  // 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($variables['page']['#views_contextual_links']) && isset($variables['attributes']['class'])) {
-    /** @var \Drupal\Core\Page\HtmlPage $page_object */
-    $page_object = $variables['page']['#page'];
-    $attributes = $page_object->getBodyAttributes();
-    $class = $attributes['class'] ?: array();
-
-    $key = array_search('contextual-region', $variables['attributes']['class'] instanceof AttributeArray ? $variables['attributes']['class']->value() : $variables['attributes']['class']);
-    if ($key !== FALSE) {
-      /** @var \Drupal\Core\Page\HtmlPage $page_object */
-      unset($class[$key]);
-      $attributes['class'] = $class;
-      $attributes['data-views-page-contextual-id'] = $variables['title_suffix']['contextual_links']['#id'];
-      $variables['#attached']['library'][] = 'views/views.contextual-links';
-    }
-  }
 }
 
 /**
