diff --git a/config/schema/menu_block.schema.yml b/config/schema/menu_block.schema.yml
index b58df67..0112779 100644
--- a/config/schema/menu_block.schema.yml
+++ b/config/schema/menu_block.schema.yml
@@ -8,6 +8,9 @@ block.settings.menu_block:*:
     follow_parent:
       type: string
       label: 'Set initial visibility level to the active menu item, or its children'
+    label_type:
+      type: string
+      label: 'Label type'
     level:
       type: integer
       label: 'Starting level'
diff --git a/menu_block.module b/menu_block.module
index 3950b92..88bffb3 100644
--- a/menu_block.module
+++ b/menu_block.module
@@ -105,3 +105,25 @@ function menu_block_theme_suggestions_menu(array $variables) {
 
   return $suggestions;
 }
+
+/**
+ * Implements hook_preprocess_hook() for "block".
+ *
+ * Set the block label with the #menu_block_configuration label if it exists.
+ */
+function menu_block_preprocess_block(&$variables) {
+  if (isset($variables['content']['#menu_block_configuration']['label'])) {
+    $config_label = $variables['content']['#menu_block_configuration']['label'];
+    // Some block twig templates (especially classy + bartik from core) use
+    // `{{ configuration.label }}` to print the label. Others just use
+    // `{{ label }}`. Therefore, we have to set both template variables for
+    // this to work consistently.
+    $variables['label'] = !empty($variables['configuration']['label_display']) ? $config_label : '';
+  }
+  // Even without $variables['content']['#menu_block_configuration']['label'] we
+  // need to change the label. For example, this happens when there are no menu
+  // items to render. But we still need to set the block label.
+  if (isset($variables['label'])) {
+    $variables['configuration']['label'] = $variables['label'];
+  }
+}
diff --git a/src/Plugin/Block/MenuBlock.php b/src/Plugin/Block/MenuBlock.php
index df28a31..ac58898 100644
--- a/src/Plugin/Block/MenuBlock.php
+++ b/src/Plugin/Block/MenuBlock.php
@@ -3,8 +3,10 @@
 namespace Drupal\menu_block\Plugin\Block;
 
 use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Menu\MenuParentFormSelectorInterface;
+use Drupal\Core\Menu\MenuTreeParameters;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\system\Entity\Menu;
 use Drupal\system\Plugin\Block\SystemMenuBlock;
@@ -26,6 +28,23 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 class MenuBlock extends SystemMenuBlock {
 
   /**
+   * Constant definition options for block label type.
+   */
+  const LABEL_BLOCK = 'block';
+  const LABEL_MENU = 'menu';
+  const LABEL_ACTIVE_ITEM = 'active_item';
+  const LABEL_PARENT = 'parent';
+  const LABEL_ROOT = 'root';
+  const LABEL_FIXED = 'fixed';
+
+  /**
+   * Entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
    * The menu parent form selector service.
    *
    * @var \Drupal\Core\Menu\MenuParentFormSelectorInterface
@@ -37,8 +56,9 @@ class MenuBlock extends SystemMenuBlock {
    */
   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
     $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
-    $instance->setMenuParentFormSelector($container->get('menu.parent_form_selector'));
-
+    $instance
+      ->setMenuParentFormSelector($container->get('menu.parent_form_selector'))
+      ->setEntityTypeManager($container->get('entity_type.manager'));
     return $instance;
   }
 
@@ -56,6 +76,19 @@ class MenuBlock extends SystemMenuBlock {
   }
 
   /**
+   * Sets the entity type manager service.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager service.
+   *
+   * @return $this
+   */
+  public function setEntityTypeManager(EntityTypeManagerInterface $entity_type_manager) {
+    $this->entityTypeManager = $entity_type_manager;
+    return $this;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function blockForm($form, FormStateInterface $form_state) {
@@ -89,6 +122,26 @@ class MenuBlock extends SystemMenuBlock {
       '#description' => $this->t('Alter the options in “Menu levels” to be relative to the fixed parent item. The block will only contain children of the selected menu link.'),
     ];
 
+    $form['advanced']['label_type'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Use as title'),
+      '#description' => $this->t('Replace the block title with an item from the menu.'),
+      '#options' => [
+        self::LABEL_BLOCK => $this->t('Block title'),
+        self::LABEL_MENU => $this->t('Menu title'),
+        self::LABEL_FIXED => $this->t("Fixed menu item's title"),
+        self::LABEL_ACTIVE_ITEM => $this->t("Active item's title"),
+        self::LABEL_PARENT => $this->t("Active trail's parent title"),
+        self::LABEL_ROOT => $this->t("Active trail's root title"),
+      ],
+      '#default_value' => $config['label_type'],
+      '#states' => [
+        'visible' => [
+          ':input[name="settings[label_display]"]' => ['checked' => TRUE],
+        ],
+      ],
+    ];
+
     $form['style'] = [
       '#type' => 'details',
       '#title' => $this->t('HTML and style options'),
@@ -164,6 +217,7 @@ class MenuBlock extends SystemMenuBlock {
     $this->configuration['expand'] = $form_state->getValue('expand');
     $this->configuration['parent'] = $form_state->getValue('parent');
     $this->configuration['suggestion'] = $form_state->getValue('suggestion');
+    $this->configuration['label_type'] = $form_state->getValue('label_type');
   }
 
   /**
@@ -273,9 +327,17 @@ class MenuBlock extends SystemMenuBlock {
     $tree = $this->menuTree->transform($tree, $manipulators);
     $build = $this->menuTree->build($tree);
 
+    $label = $this->getBlockLabel() ?: $this->label();
+    // Set the block's #title (label) to the dynamic value.
+    $build['#title'] = [
+      '#markup' => $label,
+    ];
     if (!empty($build['#theme'])) {
       // Add the configuration for use in menu_block_theme_suggestions_menu().
       $build['#menu_block_configuration'] = $this->configuration;
+      // Set the generated label into the configuration array so it is
+      // propagated to the theme preprocessor and template(s) as needed.
+      $build['#menu_block_configuration']['label'] = $label;
       // Remove the menu name-based suggestion so we can control its precedence
       // better in menu_block_theme_suggestions_menu().
       $build['#theme'] = 'menu';
@@ -311,6 +373,7 @@ class MenuBlock extends SystemMenuBlock {
       'expand' => 0,
       'parent' => $this->getDerivativeId() . ':',
       'suggestion' => strtr($this->getDerivativeId(), '-', '_'),
+      'label_type' => self::LABEL_BLOCK,
     ];
   }
 
@@ -324,4 +387,165 @@ class MenuBlock extends SystemMenuBlock {
     return FALSE;
   }
 
+  /**
+   * Gets the configured block label.
+   *
+   * @return string
+   *   The configured label.
+   */
+  public function getBlockLabel() {
+    switch ($this->configuration['label_type']) {
+      case self::LABEL_MENU:
+        return $this->getMenuTitle();
+
+      case self::LABEL_ACTIVE_ITEM:
+        return $this->getActiveItemTitle();
+
+      case self::LABEL_PARENT:
+        return $this->getActiveTrailParentTitle();
+
+      case self::LABEL_ROOT:
+        return $this->getActiveTrailRootTitle();
+
+      case self::LABEL_FIXED:
+        return $this->getFixedMenuItemTitle();
+
+      default:
+        return $this->label();
+    }
+  }
+
+  /**
+   * Gets the label of the configured menu.
+   *
+   * @return string|null
+   *   Menu label or NULL if no menu exists.
+   */
+  protected function getMenuTitle() {
+    try {
+      $menu = $this->entityTypeManager->getStorage('menu')
+        ->load($this->getDerivativeId());
+    }
+    catch (\Exception $e) {
+      return NULL;
+    }
+
+    return $menu ? $menu->label() : NULL;
+  }
+
+  /**
+   * Gets the title of a fixed parent item.
+   *
+   * @return string|null
+   *   Title of the configured (fixed) parent item, or NULL if there is none.
+   */
+  protected function getFixedMenuItemTitle() {
+    $parent = $this->configuration['parent'];
+
+    if ($parent) {
+      $fixed_menu_link_id = str_replace($this->getDerivativeId() . ':', '', $parent);
+      return $this->getLinkTitleFromLink($fixed_menu_link_id);
+    }
+  }
+
+  /**
+   * Gets the active menu item's title.
+   *
+   * @return string|null
+   *   Currently active menu item title or NULL if there's nothing active.
+   */
+  protected function getActiveItemTitle() {
+    /** @var array $active_trail_ids */
+    $active_trail_ids = $this->getDerivativeActiveTrailIds();
+    if ($active_trail_ids) {
+      return $this->getLinkTitleFromLink(reset($active_trail_ids));
+    }
+  }
+
+  /**
+   * Gets the title of the parent of the active menu item.
+   *
+   * @return string|null
+   *   The title of the parent of the active menu item, the title of the active
+   *   item if it has no parent, or NULL if there's no active menu item.
+   */
+  protected function getActiveTrailParentTitle() {
+    /** @var array $active_trail_ids */
+    $active_trail_ids = $this->getDerivativeActiveTrailIds();
+    if ($active_trail_ids) {
+      if (count($active_trail_ids) === 1) {
+        return $this->getActiveItemTitle();
+      }
+      return $this->getLinkTitleFromLink(next($active_trail_ids));
+    }
+  }
+
+  /**
+   * Gets the current menu item's root menu item title.
+   *
+   * @return string|null
+   *   The root menu item title or NULL if there's no active item.
+   */
+  protected function getActiveTrailRootTitle() {
+    /** @var array $active_trail_ids */
+    $active_trail_ids = $this->getDerivativeActiveTrailIds();
+
+    if ($active_trail_ids) {
+      return $this->getLinkTitleFromLink(end($active_trail_ids));
+    }
+  }
+
+  /**
+   * Gets an array of the active trail menu link items.
+   *
+   * @return array
+   *   The active trail menu item IDs.
+   */
+  protected function getDerivativeActiveTrailIds() {
+    $menu_id = $this->getDerivativeId();
+    return array_filter($this->menuActiveTrail->getActiveTrailIds($menu_id));
+  }
+
+  /**
+   * Gets the title of a given menu item ID.
+   *
+   * @param string $link_id
+   *   The menu item ID.
+   *
+   * @return string|null
+   *   The menu item title or NULL if the given menu item can't be found.
+   */
+  protected function getLinkTitleFromLink($link_id) {
+    $parameters = new MenuTreeParameters();
+    $menu = $this->menuTree->load($this->getDerivativeId(), $parameters);
+    $link = $this->findLinkInTree($menu, $link_id);
+    if ($link) {
+      return $link->link->getTitle();
+    }
+  }
+
+  /**
+   * Gets the menu link item from the menu tree.
+   *
+   * @param array $menu_tree
+   *   Associative array containing the menu link tree data.
+   * @param string $link_id
+   *   Menu link id to find.
+   *
+   * @return \Drupal\Core\Menu\MenuLinkTreeElement|null
+   *   The link element from the given menu tree or NULL if it can't be found.
+   */
+  protected function findLinkInTree(array $menu_tree, $link_id) {
+    if (isset($menu_tree[$link_id])) {
+      return $menu_tree[$link_id];
+    }
+    /** @var \Drupal\Core\Menu\MenuLinkTreeElement $link */
+    foreach ($menu_tree as $link) {
+      $link = $this->findLinkInTree($link->subtree, $link_id);
+      if ($link) {
+        return $link;
+      }
+    }
+  }
+
 }
diff --git a/tests/src/Functional/MenuBlockTest.php b/tests/src/Functional/MenuBlockTest.php
index c2a0bb6..d491235 100644
--- a/tests/src/Functional/MenuBlockTest.php
+++ b/tests/src/Functional/MenuBlockTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\menu_block\Functional;
 
+use Drupal\menu_block\Plugin\Block\MenuBlock;
 use Drupal\Tests\BrowserTestBase;
 
 /**
@@ -458,4 +459,86 @@ class MenuBlockTest extends BrowserTestBase {
     ], 'Found expected menu suggestions.');
   }
 
+  /**
+   * Test menu block label type options.
+   */
+  public function testMenuBlockTitleOptions() {
+    // Create a block, and edit it repeatedly to test the title display options.
+    $block_id = 'main';
+    $this->drupalPostForm('admin/structure/block/add/menu_block:main', [
+      'id' => $block_id,
+      'settings[label]' => 'Block title',
+      'settings[label_display]' => TRUE,
+      'settings[parent]' => 'main:' . $this->links['child-1'],
+      'region' => 'primary_menu',
+    ], 'Save block');
+
+    $options = [
+      'block label' => [
+        'option' => MenuBlock::LABEL_BLOCK,
+        'title' => 'Block title',
+      ],
+      'menu label' => [
+        'option' => MenuBlock::LABEL_MENU,
+        'title' => 'Main navigation',
+      ],
+      'fixed menu item' => [
+        'option' => MenuBlock::LABEL_FIXED,
+        'title' => 'child-1 menu item',
+      ],
+      'fixed menu item parent' => [
+        'option' => MenuBlock::LABEL_FIXED,
+        'title' => 'child-1 menu item',
+        'test_link' => 'menu-block-test/hierarchy/parent',
+      ],
+      'active item' => [
+        'option' => MenuBlock::LABEL_ACTIVE_ITEM,
+        'title' => 'child-1-1 menu item',
+      ],
+      'parent item' => [
+        'option' => MenuBlock::LABEL_PARENT,
+        'title' => 'child-1 menu item',
+      ],
+      'parent item top level' => [
+        'option' => MenuBlock::LABEL_PARENT,
+        'title' => 'parent menu item',
+        'test_link' => 'menu-block-test/hierarchy/parent',
+      ],
+      'parent item 2' => [
+        'option' => MenuBlock::LABEL_PARENT,
+        'title' => 'parent menu item',
+        'test_link' => 'menu-block-test/hierarchy/parent/child-1',
+      ],
+      'parent item 3' => [
+        'option' => MenuBlock::LABEL_PARENT,
+        'title' => 'child-1 menu item',
+        'test_link' => 'menu-block-test/hierarchy/parent/child-1/child-1-2',
+      ],
+      'menu root' => [
+        'option' => MenuBlock::LABEL_ROOT,
+        'title' => 'parent menu item',
+      ],
+      'menu root 2' => [
+        'option' => MenuBlock::LABEL_ROOT,
+        'title' => 'parent menu item',
+        'test_link' => 'menu-block-test/hierarchy/parent/child-1',
+      ],
+      'menu root 3' => [
+        'option' => MenuBlock::LABEL_ROOT,
+        'title' => 'parent menu item',
+        'test_link' => 'menu-block-test/hierarchy/parent/child-1/child-1-2',
+      ],
+    ];
+
+    foreach ($options as $option) {
+      $this->drupalPostForm('admin/structure/block/manage/main', [
+        'settings[label_type]' => $option['option'],
+      ], 'Save block');
+      $test_link = empty($option['test_link']) ? 'menu-block-test/hierarchy/parent/child-1/child-1-1' : $option['test_link'];
+      $this->drupalGet($test_link);
+      $this->assertSession()
+        ->elementTextContains('css', 'h2#block-main-menu', $option['title']);
+    }
+  }
+
 }
