diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index e59615c..e5310eb 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -1555,93 +1555,82 @@ function _menu_tree_data(&$links, $parents, $depth) {
 }
 
 /**
- * Implements template_preprocess_HOOK() for theme_menu_tree().
+ * Prepares variables for menu tree templates.
+ *
+ * Default template: menu-tree.html.twig.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - tree: A render array for a menu tree.
  */
 function template_preprocess_menu_tree(&$variables) {
   $variables['tree'] = $variables['tree']['#children'];
 }
 
 /**
- * Returns HTML for a wrapper for a menu sub-tree.
+ * Prepares variables for menu link plus submenu templates.
  *
- * @param $variables
- *   An associative array containing:
- *   - tree: An HTML string containing the tree's items.
+ * Default template: menu-link.html.twig.
  *
- * @see template_preprocess_menu_tree()
- * @ingroup themeable
- */
-function theme_menu_tree($variables) {
-  return '<ul class="menu">' . $variables['tree'] . '</ul>';
-}
-
-/**
- * Returns HTML for a menu link and submenu.
- *
- * @param $variables
+ * @param array $variables
  *   An associative array containing:
  *   - element: Structured array data for a menu link.
- *
- * @ingroup themeable
  */
-function theme_menu_link(array $variables) {
+function template_preprocess_menu_link(&$variables) {
   $element = $variables['element'];
-  $sub_menu = '';
 
-  if ($element['#below']) {
-    $sub_menu = drupal_render($element['#below']);
-  }
-  $output = l($element['#title'], $element['#href'], $element['#localized_options']);
-  return '<li' . new Attribute($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
+  $variables['sub_menu'] = $element['#below'];
+  $variables['link'] = l($element['#title'], $element['#href'], $element['#localized_options']);
+  $variables['wrapper_attributes'] = new Attribute($element['#attributes']);
 }
 
 /**
- * Returns HTML for a single local task link.
+ * Prepares variables for single local task link templates.
  *
- * @param $variables
+ * Default template: menu-local-task.html.twig.
+ *
+ * @param $array variables
  *   An associative array containing:
  *   - element: A render element containing:
  *     - #link: A menu link array with 'title', 'href', and 'localized_options'
  *       keys.
  *     - #active: A boolean indicating whether the local task is active.
- *
- * @ingroup themeable
  */
-function theme_menu_local_task($variables) {
+function template_preprocess_menu_local_task(&$variables) {
   $link = $variables['element']['#link'];
   $link += array(
     'localized_options' => array(),
   );
-  $link_text = $link['title'];
 
+  $variables['wrapper_attributes'] = new Attribute();
+  $variables['active'] = FALSE;
   if (!empty($variables['element']['#active'])) {
-    // Add text to indicate active tab for non-visual users.
-    $active = '<span class="element-invisible">' . t('(active tab)') . '</span>';
+    $variables['wrapper_attributes']['class'] = array('active');
+    $variables['active'] = TRUE;
 
     // If the link does not contain HTML already, check_plain() it now.
-    // After we set 'html'=TRUE the link will not be sanitized by l().
+    // After we set 'html' = TRUE, the link will not be sanitized by l().
     if (empty($link['localized_options']['html'])) {
       $link['title'] = check_plain($link['title']);
     }
     $link['localized_options']['html'] = TRUE;
-    $link_text = t('!local-task-title!active', array('!local-task-title' => $link['title'], '!active' => $active));
   }
 
-  return '<li' . (!empty($variables['element']['#active']) ? ' class="active"' : '') . '>' . l($link_text, $link['href'], $link['localized_options']) . '</li>';
+  $variables['link'] = l($link['title'], $link['href'], $link['localized_options']);
 }
 
 /**
- * Returns HTML for a single local action link.
+ * Prepares variables for single local action link templates.
  *
- * @param $variables
+ * Default template: menu-local-action.html.twig.
+ *
+ * @param array $variables
  *   An associative array containing:
  *   - element: A render element containing:
  *     - #link: A menu link array with 'title', 'href', and 'localized_options'
  *       keys.
- *
- * @ingroup themeable
  */
-function theme_menu_local_action($variables) {
+function template_preprocess_menu_local_action(&$variables) {
   $link = $variables['element']['#link'];
   $link += array(
     'href' => '',
@@ -1650,11 +1639,7 @@ function theme_menu_local_action($variables) {
   $link['localized_options']['attributes']['class'][] = 'button';
   $link['localized_options']['attributes']['class'][] = 'button-action';
 
-  $output = '<li>';
-  $output .= l($link['title'], $link['href'], $link['localized_options']);
-  $output .= "</li>";
-
-  return $output;
+  $variables['link'] = l($link['title'], $link['href'], $link['localized_options']);
 }
 
 /**
@@ -2251,6 +2236,23 @@ function theme_menu_local_tasks(&$variables) {
 }
 
 /**
+ * Prepares variables for primary and secondary local task templates.
+ *
+ * Default template: menu-local-tasks.html.twig.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - primary: (optional) An array of local tasks (tabs).
+ *   - secondary: (optional) An array of local tasks (tabs).
+ *
+ * @see menu_local_tasks()
+ */
+function template_preprocess_menu_local_tasks(&$variables) {
+  $variables['primary_tasks'] = (!empty($variables['primary'])) ? drupal_render($variables['primary']) : FALSE;
+  $variables['secondary_tasks'] = (!empty($variables['secondary'])) ? drupal_render($variables['secondary']) : FALSE;
+}
+
+/**
  * Sets (or gets) the active menu for the current page.
  *
  * The active menu for the page determines the active trail.
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 4c0e580..c7a805b 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -3255,18 +3255,23 @@ function drupal_common_theme() {
     // From menu.inc.
     'menu_link' => array(
       'render element' => 'element',
+      'template' => 'menu-link',
     ),
     'menu_tree' => array(
       'render element' => 'tree',
+      'template' => 'menu-tree',
     ),
     'menu_local_task' => array(
       'render element' => 'element',
+      'template' => 'menu-local-task',
     ),
     'menu_local_action' => array(
       'render element' => 'element',
+      'template' => 'menu-local-action',
     ),
     'menu_local_tasks' => array(
       'variables' => array('primary' => array(), 'secondary' => array()),
+      'template' => 'menu-local-tasks',
     ),
     // From form.inc.
     'input' => array(
diff --git a/core/modules/system/templates/menu-link.html.twig b/core/modules/system/templates/menu-link.html.twig
new file mode 100644
index 0000000..66082b2
--- /dev/null
+++ b/core/modules/system/templates/menu-link.html.twig
@@ -0,0 +1,22 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a menu link and submenu.
+ *
+ * Available variables:
+ * - wrapper_attributes: HTML attributes for the wrapper element.
+ * - link: An HTML string representing the rendered link.
+ * - sub_menu: Rendered list item children of the element.
+ *
+ * Note: This template renders the content for each individual menu item in
+ * menu-local-tasks.html.twig.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_menu_link()
+ *
+ * @ingroup themeable
+ */
+#}
+<li class="{{ wrapper_attributes.class }}"{{ wrapper_attributes }}>
+  {{ link }}{{ sub_menu }}
+</li>
diff --git a/core/modules/system/templates/menu-local-action.html.twig b/core/modules/system/templates/menu-local-action.html.twig
new file mode 100644
index 0000000..08bd68b
--- /dev/null
+++ b/core/modules/system/templates/menu-local-action.html.twig
@@ -0,0 +1,15 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a single local action link.
+ *
+ * Available variables:
+ * - link: A rendered link element.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_menu_local_action()
+ *
+ * @ingroup themeable
+ */
+#}
+<li>{{ link }}</li>
diff --git a/core/modules/system/templates/menu-local-task.html.twig b/core/modules/system/templates/menu-local-task.html.twig
new file mode 100644
index 0000000..2d1c516
--- /dev/null
+++ b/core/modules/system/templates/menu-local-task.html.twig
@@ -0,0 +1,27 @@
+{#
+/**
+ * @file
+ * Default theme implementation for a local task link.
+ *
+ * Available variables:
+ * - wrapper_attributes: HTML attributes for the wrapper element.
+ * - link: The rendered link (<a> tag).
+ *
+ * Note: This template renders the content for each individual task item in
+ * menu-local-tasks.html.twig.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_menu_local_task()
+ *
+ * @ingroup themeable
+ */
+#}
+{% spaceless %}
+<li class="{{ wrapper_attributes.class }}"{{ wrapper_attributes }}>
+  {{ link }}
+  {% if active %}
+    {# Add text to indicate active tab for non-visual users. #}
+    <span class="element-invisible">({{ 'active tab'|t }})</span>
+  {% endif %}
+</li>
+{% endspaceless %}
diff --git a/core/modules/system/templates/menu-local-tasks.html.twig b/core/modules/system/templates/menu-local-tasks.html.twig
new file mode 100755
index 0000000..2ca090d
--- /dev/null
+++ b/core/modules/system/templates/menu-local-tasks.html.twig
@@ -0,0 +1,26 @@
+{#
+/**
+ * @file
+ * Default theme implementation to display primary and secondary local tasks.
+ *
+ * Available variables:
+ * - primary_tasks: An HTML string of items representing primary tasks.
+ * - secondary_tasks: An HTML string of list items representing primary tasks.
+ *
+ * Note: Each item for both sets of tasks can be individually themed in
+ * menu-local-task.html.twig.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_menu_local_tasks()
+ *
+ * @ingroup themeable
+ */
+#}
+{% if primary_tasks %}
+  <h2 class="element-invisible">{{ 'Primary tabs'|t }}</h2>
+  <ul class="tabs primary">{{ primary_tasks }}</ul>
+{% endif %}
+{% if secondary_tasks %}
+  <h2 class="element-invisible">{{ 'Secondary tabs'|t }}</h2>
+  <ul class="tabs secondary">{{ secondary_tasks }}</ul>
+{% endif %}
diff --git a/core/modules/system/templates/menu-tree.html.twig b/core/modules/system/templates/menu-tree.html.twig
new file mode 100644
index 0000000..0dc857e
--- /dev/null
+++ b/core/modules/system/templates/menu-tree.html.twig
@@ -0,0 +1,20 @@
+{#
+/**
+ * @file
+ * Default theme implementation for the wrapper of a menu tree.
+ *
+ * Available variables:
+ * - tree: An HTML string containing the tree's items.
+ *
+ * Note: Each item in the menu tree can be individually themed in
+ * menu-link.html.twig.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_menu_tree()
+ *
+ * @ingroup themeable
+ */
+#}
+<ul class="menu">
+  {{ tree }}
+</ul>
