diff --git a/core/core.services.yml b/core/core.services.yml
index 737009bac5..d2486793b2 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1052,6 +1052,11 @@ services:
     arguments: ['@title_resolver', '@renderer']
     tags:
       - { name: render.main_content_renderer, format: drupal_dialog.off_canvas }
+  main_content_renderer.off_canvas_top:
+    class: Drupal\Core\Render\MainContent\OffCanvasRenderer
+    arguments: ['@title_resolver', '@renderer', 'top']
+    tags:
+      - { name: render.main_content_renderer, format: drupal_dialog.off_canvas_top }
   main_content_renderer.modal:
     class: Drupal\Core\Render\MainContent\ModalRenderer
     arguments: ['@title_resolver']
diff --git a/core/lib/Drupal/Core/Ajax/OpenOffCanvasDialogCommand.php b/core/lib/Drupal/Core/Ajax/OpenOffCanvasDialogCommand.php
index da6a26e35a..4aff203161 100644
--- a/core/lib/Drupal/Core/Ajax/OpenOffCanvasDialogCommand.php
+++ b/core/lib/Drupal/Core/Ajax/OpenOffCanvasDialogCommand.php
@@ -34,8 +34,10 @@ class OpenOffCanvasDialogCommand extends OpenDialogCommand {
    *   (optional) Custom settings that will be passed to the Drupal behaviors
    *   on the content of the dialog. If left empty, the settings will be
    *   populated automatically from the current request.
+   * @param string $position
+   *   (optional) The position to render the off-canvas dialog.
    */
-  public function __construct($title, $content, array $dialog_options = [], $settings = NULL) {
+  public function __construct($title, $content, array $dialog_options = [], $settings = NULL, $position = 'right') {
     parent::__construct('#drupal-off-canvas', $title, $content, $dialog_options, $settings);
     $this->dialogOptions['modal'] = FALSE;
     $this->dialogOptions['autoResize'] = FALSE;
@@ -46,7 +48,7 @@ public function __construct($title, $content, array $dialog_options = [], $setti
     //   empty set of buttons until https://www.drupal.org/node/2793343 is in.
     $this->dialogOptions['buttons'] = [];
     if (empty($dialog_options['dialogClass'])) {
-      $this->dialogOptions['dialogClass'] = 'ui-dialog-off-canvas';
+      $this->dialogOptions['dialogClass'] = "ui-dialog-off-canvas ui-dialog-position-$position";
     }
     // If no width option is provided then use the default width to avoid the
     // dialog staying at the width of the previous instance when opened
diff --git a/core/lib/Drupal/Core/Render/MainContent/OffCanvasRenderer.php b/core/lib/Drupal/Core/Render/MainContent/OffCanvasRenderer.php
index 55bf8eb7d1..df4e488bc5 100644
--- a/core/lib/Drupal/Core/Render/MainContent/OffCanvasRenderer.php
+++ b/core/lib/Drupal/Core/Render/MainContent/OffCanvasRenderer.php
@@ -23,6 +23,13 @@ class OffCanvasRenderer extends DialogRenderer {
    */
   protected $renderer;
 
+  /**
+   * The position to render the off-canvas dialog.
+   *
+   * @var string
+   */
+  protected $position;
+
   /**
    * Constructs a new OffCanvasRenderer.
    *
@@ -30,10 +37,13 @@ class OffCanvasRenderer extends DialogRenderer {
    *   The title resolver.
    * @param \Drupal\Core\Render\RendererInterface $renderer
    *   The renderer.
+   * @param string $position
+   *   (optional) The position to render the off-canvas dialog.
    */
-  public function __construct(TitleResolverInterface $title_resolver, RendererInterface $renderer) {
+  public function __construct(TitleResolverInterface $title_resolver, RendererInterface $renderer, $position = 'right') {
     parent::__construct($title_resolver);
     $this->renderer = $renderer;
+    $this->position = $position;
   }
 
   /**
@@ -55,7 +65,7 @@ public function renderResponse(array $main_content, Request $request, RouteMatch
     // Determine the title: use the title provided by the main content if any,
     // otherwise get it from the routing information.
     $options = $request->request->get('dialogOptions', []);
-    $response->addCommand(new OpenOffCanvasDialogCommand($title, $content, $options));
+    $response->addCommand(new OpenOffCanvasDialogCommand($title, $content, $options, NULL, $this->position));
     return $response;
   }
 
