diff --git a/core/includes/common.inc b/core/includes/common.inc
index a7584d3..2e86c19 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -3380,6 +3380,13 @@ function drupal_pre_render_link($element) {
     $element['#options']['attributes'] += $element['#attributes'];
   }
 
+  // Merge the provided attributes on top of the default attributes
+  // provided by the element definition.
+  if (isset($element['#default_attributes'])) {
+    $element['#options'] += array('attributes' => array());
+    $element['#options']['attributes'] = NestedArray::mergeDeep($element['#default_attributes'], $element['#options']['attributes']);
+  }
+
   // This #pre_render callback can be invoked from inside or outside of a Form
   // API context, and depending on that, a HTML ID may be already set in
   // different locations. #options should have precedence over Form API's #id.
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index aa558b2..862890a 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1847,18 +1847,6 @@ function template_preprocess_feed_icon(&$variables) {
 }
 
 /**
- * Returns HTML for a "more" link, like those used in blocks.
- *
- * @param $variables
- *   An associative array containing:
- *   - url: The URL of the main page.
- *   - title: A descriptive verb for the link, like 'Read more'.
- */
-function theme_more_link($variables) {
-  return '<div class="more-link">' . l(t('More'), $variables['url'], array('attributes' => array('title' => $variables['title']))) . '</div>';
-}
-
-/**
  * Returns HTML for an indentation div; used for drag and drop tables.
  *
  * @param $variables
@@ -2613,9 +2601,6 @@ function drupal_common_theme() {
       'variables' => array('url' => NULL, 'title' => NULL),
       'template' => 'feed-icon',
     ),
-    'more_link' => array(
-      'variables' => array('url' => NULL, 'title' => NULL)
-    ),
     'progress_bar' => array(
       'variables' => array('label' => NULL, 'percent' => NULL, 'message' => NULL),
       'template' => 'progress-bar',
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Block/AggregatorFeedBlock.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Block/AggregatorFeedBlock.php
index 767639e..46ab8f2 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Block/AggregatorFeedBlock.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/Block/AggregatorFeedBlock.php
@@ -133,9 +133,9 @@ public function build() {
     if ($feed = $this->storageController->load($this->configuration['feed'])) {
       $result = $this->connection->queryRange("SELECT * FROM {aggregator_item} WHERE fid = :fid ORDER BY timestamp DESC, iid DESC", 0, $this->configuration['block_count'], array(':fid' => $feed->id()));
       $more_link = array(
-        '#theme' => 'more_link',
-        '#url' => 'aggregator/sources/' . $feed->id(),
-        '#title' => t("View this feed's recent news."),
+        '#type' => 'more_link',
+        '#href' => 'aggregator/sources/' . $feed->id(),
+        '#attributes' => array('title' => $this->t("View this feed's recent news.")),
       );
       $read_more = drupal_render($more_link);
       $items = array();
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index 18e4149..8540c9c 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -582,7 +582,11 @@ function forum_block_view_pre_render($elements) {
   $result = $elements['#query']->execute();
   if ($node_title_list = node_title_list($result)) {
     $elements['forum_list'] = $node_title_list;
-    $elements['forum_more'] = array('#theme' => 'more_link', '#url' => 'forum', '#title' => t('Read the latest forum topics.'));
+    $elements['forum_more'] = array(
+      '#type' => 'more_link',
+      '#href' => 'forum',
+      '#attributes' => array('title' => t('Read the latest forum topics.')),
+    );
   }
   return $elements;
 }
diff --git a/core/modules/system/css/system.theme.css b/core/modules/system/css/system.theme.css
index 9a0153d..a256f30 100644
--- a/core/modules/system/css/system.theme.css
+++ b/core/modules/system/css/system.theme.css
@@ -119,7 +119,7 @@ abbr.form-required, abbr.tabledrag-changed, abbr.ajax-changed {
 }
 
 /**
- * Markup generated by theme_more_link().
+ * Markup generated by #type 'link'.
  */
 .more-link {
   text-align: right; /* LTR */
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
index 4b22a29..f544829 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/RenderElementTypesTest.php
@@ -254,4 +254,50 @@ function testMaintenancePage() {
     $this->assertElements($elements);
   }
 
+  /**
+   * Tests system #type 'more_link'.
+   */
+  function testMoreLink() {
+    $elements = array(
+      // Test more_link anchor tag generation without class attributes to test default.
+      array(
+        'name' => "#type 'more_link' anchor tag generation without extra classes",
+        'value' => array(
+          '#type' => 'more_link',
+          '#href' => 'http://drupal.org',
+        ),
+        'expected' => '//a[@href="http://drupal.org" and @class="more-link" and text()="More"]',
+      ),
+      // Test more_link anchor tag generation with title change.
+      array(
+        'name' => "#type 'more_link' anchor tag generation with different link text",
+        'value' => array(
+          '#type' => 'more_link',
+          '#href' => 'http://drupal.org',
+          '#title' => 'More Titles',
+        ),
+        'expected' => '//a[@href="http://drupal.org" and @class="more-link" and text()="More Titles"]',
+      ),
+      // Test more_link anchor tag generation without class attributes to test additional classes.
+      array(
+        'name' => "#type 'more_link' anchor tag generation with extra classes",
+        'value' => array(
+          '#type' => 'more_link',
+          '#href' => 'http://drupal.org',
+          '#attributes' => array(
+            'title' => 'description',
+            'class' => array('drupal', 'test'),
+          ),
+        ),
+        'expected' => '//a[@href="http://drupal.org" and @title="description" and contains(@class, "more-link") and contains(@class, "drupal") and contains(@class, "test") and text()="More"]',
+      ),
+    );
+
+    foreach($elements as $element) {
+      $xml = new \SimpleXMLElement(drupal_render($element['value']));
+      $result = $xml->xpath($element['expected']);
+      $this->assertTrue($result, '"' . $element['name'] . '" input rendered correctly by drupal_render().');
+    }
+  }
+
 }
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 5e23103..7c62da8 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -545,6 +545,11 @@ function system_element_info() {
   $types['link'] = array(
     '#pre_render' => array('drupal_pre_render_link'),
   );
+  // A "more" link, like those used in blocks.
+  $types['more_link'] = $types['link'] + array(
+    '#title' => t('More'),
+    '#default_attributes' => array('class' => array('more-link')),
+  );
   $types['fieldset'] = array(
     '#value' => NULL,
     '#process' => array('form_process_group', 'ajax_process_form'),
diff --git a/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php b/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php
index d3676e0..3f4eb42 100644
--- a/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php
+++ b/core/modules/system/tests/modules/theme_test/lib/Drupal/theme_test/EventSubscriber/ThemeTestSubscriber.php
@@ -43,9 +43,9 @@ public function onRequest(GetResponseEvent $event) {
       // theme system is initialized this early, it is still capable of
       // returning output and theming the page as a whole.
       $more_link = array(
-        '#theme' => 'more_link',
-        '#url' => 'user',
-        '#title' => 'Themed output generated in a KernelEvents::REQUEST listener',
+        '#type' => 'more_link',
+        '#href' => 'user',
+        '#attributes' => array('title' => 'Themed output generated in a KernelEvents::REQUEST listener'),
       );
       $GLOBALS['theme_test_output'] = drupal_render($more_link);
     }
