diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 2c94b6c..945e286 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -33,21 +33,6 @@
  */
 
 /**
- * Mark content as read.
- */
-const MARK_READ = 0;
-
-/**
- * Mark content as being new.
- */
-const MARK_NEW = 1;
-
-/**
- * Mark content as being updated.
- */
-const MARK_UPDATED = 2;
-
-/**
  * A responsive table class; hide table cell on narrow devices.
  *
  * Indicates that a column has medium priority and thus can be hidden on narrow
@@ -1746,7 +1731,7 @@ function drupal_common_theme() {
       'variables' => array('style' => NULL),
     ),
     'mark' => array(
-      'variables' => array('status' => MARK_NEW),
+      'variables' => array('status' => t('new'), 'type' => 'info'),
     ),
     'item_list' => array(
       'variables' => array('items' => array(), 'title' => '', 'list_type' => 'ul', 'wrapper_attributes' => array(), 'attributes' => array(), 'empty' => NULL, 'context' => array()),
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index dbeccb6..9e5a2e6 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -711,8 +711,18 @@ function template_preprocess_comment(&$variables) {
   if (isset($comment->in_preview)) {
     $variables['status'] = 'preview';
   }
-  else {
-    $variables['status'] = $comment->isPublished() ? 'published' : 'unpublished';
+  elseif (!$comment->isPublished()) {
+    $variables['status'] = 'unpublished';
+  }
+
+  // Create markers to display the status.
+  $variables['markers'] = array();
+  if (isset($variables['status'])) {
+    $variables['markers'][] = array(
+      '#theme' => 'mark',
+      '#status' => $variables['status'],
+      '#type' => 'warning',
+    );
   }
 
   // Add comment author user ID. Necessary for the comment-by-viewer library.
diff --git a/core/modules/comment/src/Tests/CommentAnonymousTest.php b/core/modules/comment/src/Tests/CommentAnonymousTest.php
index b7e5bd8..b67dd3c 100644
--- a/core/modules/comment/src/Tests/CommentAnonymousTest.php
+++ b/core/modules/comment/src/Tests/CommentAnonymousTest.php
@@ -48,7 +48,7 @@ function testAnonymous() {
     $edit['comment_body[0][value]'] = $body;
     $this->drupalPostForm($this->node->urlInfo(), $edit, t('Preview'));
     // Cannot use assertRaw here since both title and body are in the form.
-    $preview = (string) $this->cssSelect('.preview')[0]->asXML();
+    $preview = (string) $this->cssSelect('.comment.by-anonymous')[0]->asXML();
     $this->assertTrue(strpos($preview, $title) !== FALSE, 'Anonymous user can preview comment title.');
     $this->assertTrue(strpos($preview, $body) !== FALSE, 'Anonymous user can preview comment body.');
 
diff --git a/core/modules/comment/src/Tests/CommentCSSTest.php b/core/modules/comment/src/Tests/CommentCSSTest.php
index 47a31cc..cd92ed0 100644
--- a/core/modules/comment/src/Tests/CommentCSSTest.php
+++ b/core/modules/comment/src/Tests/CommentCSSTest.php
@@ -115,7 +115,7 @@ function testCommentClasses() {
       }
 
       // Verify the unpublished class.
-      $comments = $this->xpath('//*[contains(@class, "comment") and contains(@class, "unpublished")]');
+      $comments = $this->xpath('//*[contains(@class, "comment")]//span[.="unpublished"]');
       if ($case['comment_status'] == CommentInterface::NOT_PUBLISHED && $case['user'] == 'admin') {
         $this->assertTrue(count($comments) == 1, 'unpublished class found.');
       }
diff --git a/core/modules/comment/src/Tests/CommentPreviewTest.php b/core/modules/comment/src/Tests/CommentPreviewTest.php
index 2a9b197..73eadc3 100644
--- a/core/modules/comment/src/Tests/CommentPreviewTest.php
+++ b/core/modules/comment/src/Tests/CommentPreviewTest.php
@@ -76,7 +76,7 @@ function testCommentPreview() {
     $this->assertFieldByName('comment_body[0][value]', $edit['comment_body[0][value]'], 'Comment field displayed.');
 
     // Check that the user picture is displayed.
-    $this->assertFieldByXPath("//article[contains(@class, 'preview')]//div[contains(@class, 'user-picture')]//img", NULL, 'User picture displayed.');
+    $this->assertFieldByXPath('//article[contains(@class, "comment") and span[.="preview"]]//div[contains(@class, "user-picture")]//img', NULL, 'User picture displayed.');
   }
 
   /**
diff --git a/core/modules/comment/templates/comment.html.twig b/core/modules/comment/templates/comment.html.twig
index 14c52eb..2b7bc47 100644
--- a/core/modules/comment/templates/comment.html.twig
+++ b/core/modules/comment/templates/comment.html.twig
@@ -74,6 +74,7 @@
     indicator here would break the render cache.
   #}
   <mark class="hidden" data-comment-timestamp="{{ new_indicator_timestamp }}"></mark>
+  {{ markers }}
 
   <footer>
     {{ user_picture }}
diff --git a/core/modules/history/src/Plugin/views/field/HistoryUserTimestamp.php b/core/modules/history/src/Plugin/views/field/HistoryUserTimestamp.php
index e1d6122..bd07c69 100644
--- a/core/modules/history/src/Plugin/views/field/HistoryUserTimestamp.php
+++ b/core/modules/history/src/Plugin/views/field/HistoryUserTimestamp.php
@@ -81,7 +81,7 @@ public function render(ResultRow $values) {
     // Let's default to 'read' state.
     // This code shadows node_mark, but it reads from the db directly and
     // we already have that info.
-    $mark = MARK_READ;
+    $mark = t('read');
     if (\Drupal::currentUser()->isAuthenticated()) {
       $last_read = $this->getValue($values);
       $changed = $this->getValue($values, 'changed');
@@ -89,13 +89,13 @@ public function render(ResultRow $values) {
       $last_comment = \Drupal::moduleHandler()->moduleExists('comment') && !empty($this->options['comments']) ?  $this->getValue($values, 'last_comment') : 0;
 
       if (!$last_read && $changed > HISTORY_READ_LIMIT) {
-        $mark = MARK_NEW;
+        $mark = t('new');
       }
       elseif ($changed > $last_read && $changed > HISTORY_READ_LIMIT) {
-        $mark = MARK_UPDATED;
+        $mark = t('updated');
       }
       elseif ($last_comment > $last_read && $last_comment > HISTORY_READ_LIMIT) {
-        $mark = MARK_UPDATED;
+        $mark = t('updated');
       }
       $build = array(
         '#theme' => 'mark',
diff --git a/core/modules/history/src/Tests/Views/HistoryTimestampTest.php b/core/modules/history/src/Tests/Views/HistoryTimestampTest.php
index 44f67f9..b0e5063 100644
--- a/core/modules/history/src/Tests/Views/HistoryTimestampTest.php
+++ b/core/modules/history/src/Tests/Views/HistoryTimestampTest.php
@@ -71,7 +71,7 @@ public function testHandlers() {
     $this->assertEqual(count($view->result), 2);
     $output = $view->preview();
     $this->setRawContent(\Drupal::service('renderer')->renderRoot($output));
-    $result = $this->xpath('//span[@class=:class]', array(':class' => 'marker'));
+    $result = $this->xpath('//*[contains(@class, "views-row")]//span[.="read"]');
     $this->assertEqual(count($result), 1, 'Just one node is marked as new');
 
     // Test the history filter.
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 182def1..24e2f75 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -217,18 +217,18 @@ function node_mark($nid, $timestamp) {
   $cache = &drupal_static(__FUNCTION__, array());
 
   if (\Drupal::currentUser()->isAnonymous() || !\Drupal::moduleHandler()->moduleExists('history')) {
-    return MARK_READ;
+    return t('read');
   }
   if (!isset($cache[$nid])) {
     $cache[$nid] = history_read($nid);
   }
   if ($cache[$nid] == 0 && $timestamp > HISTORY_READ_LIMIT) {
-    return MARK_NEW;
+    return t('new');
   }
   elseif ($timestamp > $cache[$nid] && $timestamp > HISTORY_READ_LIMIT) {
-    return MARK_UPDATED;
+    return t('updated');
   }
-  return MARK_READ;
+  return t('read');
 }
 
 /**
@@ -612,6 +612,16 @@ function template_preprocess_node(&$variables) {
     }
   }
 
+  $variables['markers'] = array();
+  // Add a marker if the node is unpublished.
+  if(!$variables['node']->isPublished()) {
+    $variables['markers'][] = array(
+      '#theme' => 'mark',
+      '#status' => 'unpublished',
+      '#type' => 'warning'
+    );
+  }
+
   // Add article ARIA role.
   $variables['attributes']['role'] = 'article';
 }
diff --git a/core/modules/system/templates/mark.html.twig b/core/modules/system/templates/mark.html.twig
index 58adae1..ca95f47 100644
--- a/core/modules/system/templates/mark.html.twig
+++ b/core/modules/system/templates/mark.html.twig
@@ -4,19 +4,12 @@
  * Default theme implementation for a marker for new or updated content.
  *
  * Available variables:
- * - status: Number representing the marker status to display. Use the constants
- *   below for comparison:
- *   - MARK_NEW
- *   - MARK_UPDATED
- *   - MARK_READ
+ * - status: The status message to display.
+ * - type: The type of message.
  *
  * @ingroup themeable
  */
 #}
 {% if logged_in %}
-  {% if status is constant('MARK_NEW') %}
-    {{ 'New'|t }}
-  {% elseif status is constant('MARK_UPDATED') %}
-    {{ 'Updated'|t }}
-  {% endif %}
+  {{ status }}
 {% endif %}
diff --git a/core/themes/bartik/css/components/comments.css b/core/themes/bartik/css/components/comments.css
index c0c0c92..56b9b65 100644
--- a/core/themes/bartik/css/components/comments.css
+++ b/core/themes/bartik/css/components/comments.css
@@ -125,36 +125,6 @@
 [dir="rtl"] .comment .links li {
   padding: 0 0 0 0.5em;
 }
-.comment--unpublished {
-  margin-right: 5px; /* LTR */
-  padding: 5px 2px 5px 5px; /* LTR */
-  background: #fff4f4;
-}
-[dir="rtl"] .comment--unpublished {
-  margin-left: 5px;
-  margin-right: 0;
-  padding: 5px 5px 5px 2px;
-}
-
-/**
- * @todo: unpublished nodes have class .node--unpublished.
- * change this to .comment--unpublished.
- */
-.unpublished .comment-text .comment-arrow {
-  border-left: 1px solid #fff4f4;
-  border-right: 1px solid #fff4f4;
-}
-.unpublished {
-  padding: 20px 15px 0;
-}
 .comment-footer {
   display: table-row;
 }
-.comment--unpublished .comment__text:after,
-.node--unpublished .comment__text:after {
-  border-right-color: #fff4f4; /* LTR */
-}
-[dir="rtl"] .comment--unpublished .comment__content:after,
-[dir="rtl"] .node--unpublished .comment__content:after {
-  border-left-color: #fff4f4;
-}
diff --git a/core/themes/bartik/css/components/node.css b/core/themes/bartik/css/components/node.css
index 78caa34..74f6cd6 100644
--- a/core/themes/bartik/css/components/node.css
+++ b/core/themes/bartik/css/components/node.css
@@ -59,11 +59,3 @@
   text-align: left;
 }
 
-/* Unpublished node styles. */
-.node--unpublished {
-  padding: 20px 15px 0;
-}
-.node--unpublished .comment-text .comment-arrow {
-  border-left: 1px solid #fff4f4;
-  border-right: 1px solid #fff4f4;
-}
diff --git a/core/themes/bartik/templates/comment.html.twig b/core/themes/bartik/templates/comment.html.twig
index 8927db4..08db376 100644
--- a/core/themes/bartik/templates/comment.html.twig
+++ b/core/themes/bartik/templates/comment.html.twig
@@ -71,7 +71,6 @@
   set classes = [
     'comment',
     'js-comment',
-    status != 'published' ? 'comment--' ~ status,
     comment.owner.anonymous ? 'by-anonymous',
     author_id and author_id == commented_entity.getOwnerId() ? 'by-' ~ commented_entity.getEntityTypeId() ~ '-author',
     'clearfix',
@@ -84,6 +83,7 @@
     indicator here would break the render cache.
   #}
   <span class="hidden" data-comment-timestamp="{{ new_indicator_timestamp }}"></span>
+  {{ markers }}
 
   <footer class="comment__meta">
     {{ user_picture }}
diff --git a/core/themes/bartik/templates/node.html.twig b/core/themes/bartik/templates/node.html.twig
index 754b670..3234d11 100644
--- a/core/themes/bartik/templates/node.html.twig
+++ b/core/themes/bartik/templates/node.html.twig
@@ -36,8 +36,6 @@
  *   - node--promoted: Appears on nodes promoted to the front page.
  *   - node--sticky: Appears on nodes ordered above other non-sticky nodes in
  *     teaser listings.
- *   - node--unpublished: Appears on unpublished nodes visible only to site
- *     admins.
  * - title_attributes: Same as attributes, except applied to the main title
  *   tag that appears in the template.
  * - content_attributes: Same as attributes, except applied to the main
@@ -67,7 +65,6 @@
     'node--type-' ~ node.bundle|clean_class,
     node.isPromoted() ? 'node--promoted',
     node.isSticky() ? 'node--sticky',
-    not node.isPublished() ? 'node--unpublished',
     view_mode ? 'node--view-mode-' ~ view_mode|clean_class,
     'clearfix',
   ]
@@ -89,6 +86,15 @@
           {% trans %}Submitted by {{ author_name }} on {{ date }}{% endtrans %}
         </span>
         {{ metadata }}
+        {% if not node.isPublished() %}
+          {{ attach_library('classy/marker') }}
+          <div class="node__status">
+            <span class="marker marker--warning">
+              <span class="visually-hidden">{% trans %}This node is {% endtrans %}</span>
+              {% trans %}Unpublished{% endtrans %}
+            </span>
+          </div>
+        {% endif %}
       </div>
     {% endif %}
   </header>
diff --git a/core/themes/classy/classy.libraries.yml b/core/themes/classy/classy.libraries.yml
index e732669..874d7f0 100644
--- a/core/themes/classy/classy.libraries.yml
+++ b/core/themes/classy/classy.libraries.yml
@@ -25,6 +25,8 @@ base:
       css/components/tabs.css: { weight: -10 }
       css/components/textarea.css: { weight: -10 }
       css/components/ui-dialog.css: { weight: -10 }
+    theme:
+      css/layout.css: {}
 
 book-navigation:
   version: VERSION
@@ -86,6 +88,12 @@ search-results:
     component:
       css/components/search-results.css: {}
 
+marker:
+  version: VERSION
+  css:
+    theme:
+      css/components/marker.css: {}
+
 user:
   version: VERSION
   css:
diff --git a/core/themes/classy/css/components/marker.css b/core/themes/classy/css/components/marker.css
new file mode 100644
index 0000000..aa9c3a9
--- /dev/null
+++ b/core/themes/classy/css/components/marker.css
@@ -0,0 +1,27 @@
+/**
+ * @file
+ * Visual styles for status markers.
+ */
+
+.marker {
+  display: inline-block;
+  padding: 1px 3px;
+  background: #333;
+  color: #fff;
+  border-radius: 3px;
+  font-size: 0.75em;
+  letter-spacing: 0.025em;
+  text-transform: uppercase;
+}
+.marker--info {
+  background-color: #0074bd;
+}
+.marker--success {
+  background: #77b259;
+}
+.marker--warning {
+  background: #e09600;
+}
+.marker--error {
+  background: #e62600;
+}
diff --git a/core/themes/classy/css/components/node.css b/core/themes/classy/css/components/node.css
index 6b7cd52..03b74f6 100644
--- a/core/themes/classy/css/components/node.css
+++ b/core/themes/classy/css/components/node.css
@@ -3,6 +3,6 @@
  * Visual styles for nodes.
  */
 
-.node--unpublished {
-  background-color: #fff4f4;
+.node__status {
+  float: right;
 }
diff --git a/core/themes/classy/templates/content/comment.html.twig b/core/themes/classy/templates/content/comment.html.twig
index a4f7229..9cd0b7f 100644
--- a/core/themes/classy/templates/content/comment.html.twig
+++ b/core/themes/classy/templates/content/comment.html.twig
@@ -71,7 +71,6 @@
   set classes = [
     'comment',
     'js-comment',
-    status != 'published' ? status,
     comment.owner.anonymous ? 'by-anonymous',
     author_id and author_id == commented_entity.getOwnerId() ? 'by-' ~ commented_entity.getEntityTypeId() ~ '-author',
   ]
@@ -83,6 +82,7 @@
     indicator here would break the render cache.
   #}
   <mark class="hidden" data-comment-timestamp="{{ new_indicator_timestamp }}"></mark>
+  {{ markers }}
 
   <footer class="comment__meta">
     {{ user_picture }}
diff --git a/core/themes/classy/templates/content/mark.html.twig b/core/themes/classy/templates/content/mark.html.twig
index 9219915..3671291 100644
--- a/core/themes/classy/templates/content/mark.html.twig
+++ b/core/themes/classy/templates/content/mark.html.twig
@@ -4,17 +4,9 @@
  * Theme override for a marker for new or updated content.
  *
  * Available variables:
- * - status: Number representing the marker status to display. Use the constants
- *   below for comparison:
- *   - MARK_NEW
- *   - MARK_UPDATED
- *   - MARK_READ
+ * - status: The status message to display.
+ * - type: The type of message.
  */
 #}
-{% if logged_in %}
-  {% if status is constant('MARK_NEW') %}
-    <span class="marker">{{ 'New'|t }}</span>
-  {% elseif status is constant('MARK_UPDATED') %}
-    <span class="marker">{{ 'Updated'|t }}</span>
-  {% endif %}
-{% endif %}
+{{ attach_library('classy/marker') }}
+<span class="marker marker--{{ type }}">{{ status }}</span>
diff --git a/core/themes/classy/templates/content/node.html.twig b/core/themes/classy/templates/content/node.html.twig
index dbef76d..2d244ba 100644
--- a/core/themes/classy/templates/content/node.html.twig
+++ b/core/themes/classy/templates/content/node.html.twig
@@ -36,7 +36,6 @@
  *   - node--promoted: Appears on nodes promoted to the front page.
  *   - node--sticky: Appears on nodes ordered above other non-sticky nodes in
  *     teaser listings.
- *   - node--unpublished: Appears on unpublished nodes visible only to site
  *     admins.
  * - title_attributes: Same as attributes, except applied to the main title
  *   tag that appears in the template.
@@ -71,7 +70,6 @@
     'node--type-' ~ node.bundle|clean_class,
     node.isPromoted() ? 'node--promoted',
     node.isSticky() ? 'node--sticky',
-    not node.isPublished() ? 'node--unpublished',
     view_mode ? 'node--view-mode-' ~ view_mode|clean_class,
   ]
 %}
@@ -92,6 +90,7 @@
       <div{{ author_attributes.addClass('node__submitted') }}>
         {% trans %}Submitted by {{ author_name }} on {{ date }}{% endtrans %}
         {{ metadata }}
+        {{ markers }}
       </div>
     </footer>
   {% endif %}
