diff --git a/core/modules/block/block.admin.inc b/core/modules/block/block.admin.inc
index f94ce25..0b0edd4 100644
--- a/core/modules/block/block.admin.inc
+++ b/core/modules/block/block.admin.inc
@@ -8,16 +8,6 @@
 use Drupal\block\Plugin\Core\Entity\Block;
 
 /**
- * Page callback: Attaches CSS for the block region demo.
- *
- * @see block_menu()
- */
-function block_admin_demo($theme = NULL) {
-  drupal_add_css(drupal_get_path('module', 'block') . '/block.admin.css');
-  return '';
-}
-
-/**
  * Page callback: Shows the block administration page.
  *
  * @param string $theme
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index d94ec3b..6c9d41f 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -170,19 +170,16 @@ function block_menu() {
         'access arguments' => array($key),
         'file' => 'block.admin.inc',
       );
-      $items['admin/structure/block/demo/' . $key] = array(
-        'title' => check_plain($theme->info['name']),
-        'page callback' => 'block_admin_demo',
-        'page arguments' => array($key),
-        'type' => MENU_CALLBACK,
-        'access callback' => '_block_themes_access',
-        'access arguments' => array($key),
-        'theme callback' => '_block_custom_theme',
-        'theme arguments' => array($key),
-        'file' => 'block.admin.inc',
-      );
     }
   }
+  if (isset($theme)) {
+    $items['admin/structure/block/demo/%'] = array(
+      'route_name' => 'block_admin_demo',
+      'type' => MENU_CALLBACK,
+      'theme callback' => '_block_custom_theme',
+      'theme arguments' => array(4),
+    );
+  }
   return $items;
 }
 
@@ -191,7 +188,6 @@ function block_menu() {
  *
  * Path:
  * - admin/structure/block/list/% (for each theme)
- * - admin/structure/block/demo/% (for each theme)
  *
  * @param $theme
  *   Either the name of a theme or a full theme object.
@@ -236,7 +232,7 @@ function block_page_build(&$page) {
   $all_regions = system_region_list($theme);
 
   $item = menu_get_item();
-  if ($item['path'] != 'admin/structure/block/demo/' . $theme) {
+  if ($item['path'] != 'admin/structure/block/demo/%') {
     // Load all region content assigned via blocks.
     foreach (array_keys($all_regions) as $region) {
       // Assign blocks to region.
@@ -256,26 +252,23 @@ function block_page_build(&$page) {
   }
   else {
     // Append region description if we are rendering the regions demo page.
-    $item = menu_get_item();
-    if ($item['path'] == 'admin/structure/block/demo/' . $theme) {
-      $visible_regions = array_keys(system_region_list($theme, REGIONS_VISIBLE));
-      foreach ($visible_regions as $region) {
-        $description = '<div class="block-region">' . $all_regions[$region] . '</div>';
-        $page[$region]['block_description'] = array(
-          '#markup' => $description,
-          '#weight' => 15,
-        );
-      }
-      $page['page_top']['backlink'] = array(
-        '#type' => 'link',
-        '#title' => t('Exit block region demonstration'),
-        '#href' => 'admin/structure/block' . (config('system.theme')->get('default') == $theme ? '' : '/list/' . $theme),
-        // Add the "overlay-restore" class to indicate this link should restore
-        // the context in which the region demonstration page was opened.
-        '#options' => array('attributes' => array('class' => array('block-demo-backlink', 'overlay-restore'))),
-        '#weight' => -10,
+    $visible_regions = array_keys(system_region_list($theme, REGIONS_VISIBLE));
+    foreach ($visible_regions as $region) {
+      $description = '<div class="block-region">' . $all_regions[$region] . '</div>';
+      $page[$region]['block_description'] = array(
+        '#markup' => $description,
+        '#weight' => 15,
       );
     }
+    $page['page_top']['backlink'] = array(
+      '#type' => 'link',
+      '#title' => t('Exit block region demonstration'),
+      '#href' => 'admin/structure/block' . (config('system.theme')->get('default') == $theme ? '' : '/list/' . $theme),
+      // Add the "overlay-restore" class to indicate this link should restore
+      // the context in which the region demonstration page was opened.
+      '#options' => array('attributes' => array('class' => array('block-demo-backlink', 'overlay-restore'))),
+      '#weight' => -10,
+    );
   }
 }
 
diff --git a/core/modules/block/block.routing.yml b/core/modules/block/block.routing.yml
index af247b0..2603497 100644
--- a/core/modules/block/block.routing.yml
+++ b/core/modules/block/block.routing.yml
@@ -4,3 +4,11 @@ block_admin_block_delete:
     _form: '\Drupal\block\Form\AdminBlockDeleteForm'
   requirements:
     _permission: 'administer blocks'
+
+block_admin_demo:
+  pattern: '/admin/structure/block/demo/{theme}'
+  defaults:
+    _content: '\Drupal\block\Controller\AdminController::demo'
+  requirements:
+    _access_block_theme: 'TRUE'
+    _permission: 'administer blocks'
