diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
index 093da50..7ee8566 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
@@ -182,25 +182,25 @@ function testContentTypeDirLang() {
 
     // Check if English node does not have lang tag.
     $this->drupalGet('node/' . $nodes['en']->id());
-    $pattern = '|id="node-' . $nodes['en']->id() . '"[^<>]*lang="en"|';
+    $pattern = '|class="[^"]*node--' . $nodes['en']->id() . '[^"]*"[^<>]*lang="en"|';
     $this->assertNoPattern($pattern, 'The lang tag has not been assigned to the English node.');
 
     // Check if English node does not have dir tag.
-    $pattern = '|id="node-' . $nodes['en']->id() . '"[^<>]*dir="ltr"|';
+    $pattern = '|class="[^"]*node--' . $nodes['en']->id() . '[^"]*"[^<>]*dir="ltr"|';
     $this->assertNoPattern($pattern, 'The dir tag has not been assigned to the English node.');
 
     // Check if Arabic node has lang="ar" & dir="rtl" tags.
     $this->drupalGet('node/' . $nodes['ar']->id());
-    $pattern = '|id="node-' . $nodes['ar']->id() . '"[^<>]*lang="ar" dir="rtl"|';
+    $pattern = '|class="[^"]*node--' . $nodes['ar']->id() . '[^"]*"[^<>]*lang="ar" dir="rtl"|';
     $this->assertPattern($pattern, 'The lang and dir tags have been assigned correctly to the Arabic node.');
 
     // Check if Spanish node has lang="es" tag.
     $this->drupalGet('node/' . $nodes['es']->id());
-    $pattern = '|id="node-' . $nodes['es']->id() . '"[^<>]*lang="es"|';
+    $pattern = '|class="[^"]*node--' . $nodes['es']->id() . '[^"]*"[^<>]*lang="es"|';
     $this->assertPattern($pattern, 'The lang tag has been assigned correctly to the Spanish node.');
 
     // Check if Spanish node does not have dir="ltr" tag.
-    $pattern = '|id="node-' . $nodes['es']->id() . '"[^<>]*lang="es" dir="ltr"|';
+    $pattern = '|class="[^"]*node--' . $nodes['es']->id() . '[^"]*"[^<>]*lang="es" dir="ltr"|';
     $this->assertNoPattern($pattern, 'The dir tag has not been assigned to the Spanish node.');
   }
 
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
index 67b34e7..71cef14 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
@@ -132,9 +132,9 @@ function testMultilingualDisplaySettings() {
 
     // Check if node body is showed.
     $this->drupalGet('node/' . $node->id());
-    $body = $this->xpath('//article[@id=:id]//div[@class=:class]/descendant::p', array(
-      ':id' => 'node-' . $node->id(),
-      ':class' => 'content',
+     $body = $this->xpath('//article[contains(concat(" ", normalize-space(@class), " "), :node-class)]//div[@class=:content-class]/descendant::p', array(
+      ':node-class' => $node->id() . ' ',
+      ':content-class' => 'node__content',
     ));
     $this->assertEqual(current($body), $node->body->value, 'Node body found.');
   }
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodePostSettingsTest.php b/core/modules/node/lib/Drupal/node/Tests/NodePostSettingsTest.php
index a7478a8..ba81acc 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodePostSettingsTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodePostSettingsTest.php
@@ -45,7 +45,7 @@ function testPagePostInfo() {
 
     // Check that the post information is displayed.
     $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
-    $elements = $this->xpath('//*[contains(@class,:class)]', array(':class' => 'submitted'));
+    $elements = $this->xpath('//*[contains(@class,:class)]', array(':class' => 'node__meta'));
     $this->assertEqual(count($elements), 1, 'Post information is displayed.');
     $node->delete();
 
@@ -61,7 +61,7 @@ function testPagePostInfo() {
     $this->drupalPostForm('node/add/page', $edit, t('Save'));
 
     // Check that the post information is displayed.
-    $elements = $this->xpath('//*[contains(@class,:class)]', array(':class' => 'submitted'));
+    $elements = $this->xpath('//*[contains(@class,:class)]', array(':class' => 'node__meta'));
     $this->assertEqual(count($elements), 0, 'Post information is not displayed.');
   }
 }
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php
index 9b503ff..8e2df23 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php
@@ -42,7 +42,8 @@ function setUp() {
    */
   function testNodeTitle() {
     // Create "Basic page" content with title.
-    // Add the node to the frontpage so we can test if teaser links are clickable.
+    // Add the node to the frontpage so we can test if teaser links are
+    // clickable.
     $settings = array(
       'title' => $this->randomName(8),
       'promote' => 1,
@@ -60,7 +61,7 @@ function testNodeTitle() {
     $this->assertEqual(current($this->xpath($xpath)), $node->label(), 'Node breadcrumb is equal to node title.', 'Node');
 
     // Test node title in comment preview.
-    $this->assertEqual(current($this->xpath('//article[@id=:id]/h2/a/span', array(':id' => 'node-' . $node->id()))), $node->label(), 'Node preview title is equal to node title.', 'Node');
+    $this->assertEqual(current($this->xpath('//article[contains(concat(" ", normalize-space(@class), " "), :node-class)]/h2/a/span', array(':node-class' => 'node--' . $node->id() . ' '))), $node->label(), 'Node preview title is equal to node title.', 'Node');
 
     // Test node title is clickable on teaser list (/node).
     $this->drupalGet('node');
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index b05fc2c..f9c9a8e 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -645,7 +645,7 @@ function template_preprocess_node(&$variables) {
   );
   $variables['name'] = drupal_render($username);
 
-  $variables['node_url'] = $node->url('canonical', array(
+  $variables['url'] = $node->url('canonical', array(
     'language' => $node->language(),
   ));
   $variables['label'] = $variables['elements']['title'];
@@ -669,15 +669,15 @@ function template_preprocess_node(&$variables) {
       // To change user picture settings (e.g. image style), edit the 'compact'
       // view mode on the User entity. Note that the 'compact' view mode might
       // not be configured, so remember to always check the theme setting first.
-      $variables['user_picture'] = user_view($node->getOwner(), 'compact');
+      $variables['author'] = user_view($node->getOwner(), 'compact');
     }
     else {
-      $variables['user_picture'] = array();
+      $variables['author'] = array();
     }
   }
   else {
     $variables['submitted'] = '';
-    $variables['user_picture'] = '';
+    $variables['author'] = '';
   }
 
   // Add article ARIA role.
@@ -685,23 +685,23 @@ function template_preprocess_node(&$variables) {
 
   // Gather node classes.
   $variables['attributes']['class'][] = 'node';
-  $variables['attributes']['class'][] = drupal_html_class('node-' . $node->bundle());
+  $variables['attributes']['class'][] = drupal_html_class('node--' . $node->bundle());
   if ($node->isPromoted()) {
-    $variables['attributes']['class'][] = 'promoted';
+    $variables['attributes']['class'][] = 'is-promoted';
   }
   if ($node->isSticky()) {
-    $variables['attributes']['class'][] = 'sticky';
+    $variables['attributes']['class'][] = 'is-sticky';
   }
   if (!$node->isPublished()) {
-    $variables['attributes']['class'][] = 'unpublished';
+    $variables['attributes']['class'][] = 'is-unpublished';
   }
   if ($variables['view_mode']) {
     $variables['attributes']['class'][] = drupal_html_class('view-mode-' . $variables['view_mode']);
   }
   if (isset($variables['preview'])) {
-    $variables['attributes']['class'][] = 'preview';
+    $variables['attributes']['class'][] = 'is-preview';
   }
-  $variables['content_attributes']['class'][] = 'content';
+
 }
 
 /**
@@ -1295,9 +1295,9 @@ function node_form_system_themes_admin_form_submit($form, &$form_state) {
  *
  * Next, all implementations of hook_node_access() will be called. Each
  * implementation may explicitly allow, explicitly deny, or ignore the access
- * request. If at least one module says to deny the request, it will be rejected.
- * If no modules deny the request and at least one says to allow it, the request
- * will be permitted.
+ * request. If at least one module says to deny the request, it will be
+ * rejected. If no modules deny the request and at least one says to allow it,
+ * the request will be permitted.
  *
  * If all modules ignore the access request, then the node_access table is used
  * to determine access. All node access modules are queried using
@@ -1638,7 +1638,8 @@ function node_access_rebuild($batch_mode = FALSE) {
       // Try to allocate enough time to rebuild node grants
       drupal_set_time_limit(240);
 
-      // Rebuild newest nodes first so that recent content becomes available quickly.
+      // Rebuild newest nodes first so that recent content becomes available
+      // quickly.
       $entity_query = \Drupal::entityQuery('node');
       $entity_query->sort('nid', 'DESC');
       $nids = $entity_query->execute();
diff --git a/core/modules/node/templates/node.html.twig b/core/modules/node/templates/node.html.twig
index 5bf5ad9..5c1cc12 100644
--- a/core/modules/node/templates/node.html.twig
+++ b/core/modules/node/templates/node.html.twig
@@ -8,8 +8,8 @@
  *   - id: The node ID
  *   - bundle: The type of the node, for example, "page" or "article".
  *   - authorid: The user ID of the node author.
- *   - createdtime: Formatted creation date. Preprocess functions can reformat it by
- *     calling format_date() with the desired parameters on
+ *   - createdtime: Formatted creation date. Preprocess functions can reformat
+ *     it by calling format_date() with the desired parameters on
  *     $variables['node']->getCreatedTime().
  *   - promoted: Whether the node is promoted to the front page.
  *   - sticky: Whether the node is 'sticky'. Sticky nodes are ordered above
@@ -20,12 +20,13 @@
  *   or print a subset such as {{ content.field_example }}. Use
  *   {{ content|without('field_example') %} to temporarily suppress the printing
  *   of a given child element.
- * - user_picture: The node author's picture from user-picture.html.twig.
+ * - author: The node author user entity, rendered using the "compact" view
+ *   mode.
  * - date: Formatted creation date. Preprocess functions can reformat it by
  *   calling format_date() with the desired parameters on
  *   $variables['created'].
  * - name: Themed username of node author output from theme_username().
- * - node_url: Direct URL of the current node.
+ * - url: Direct URL of the current node.
  * - display_submitted: Whether submission information should be displayed.
  * - submitted: Submission information created from name and date during
  *   template_preprocess_node().
@@ -33,17 +34,17 @@
  *   The attributes.class element may contain one or more of the following
  *   classes:
  *   - node: The current template type (also known as a "theming hook").
- *   - node-[type]: The current node type. For example, if the node is a
+ *   - node--[type]: The current node type. For example, if the node is a
  *     "Article" it would result in "node-article". Note that the machine
  *     name will often be in a short form of the human readable label.
  *   - view-mode-[view_mode]: The View Mode of the node; for example, a teaser
  *     would result in: "view-mode-teaser", and full: "view-mode-full".
- *   - preview: Whether a node is in preview mode.
+ *   - is-preview: Whether a node is in preview mode.
  *   The following are controlled through the node publishing options.
- *   - promoted: Appears on nodes promoted to the front page.
- *   - sticky: Appears on nodes ordered above other non-sticky nodes in teaser
+ *   - is-promoted: Appears on nodes promoted to the front page.
+ *   - is-sticky: Appears on nodes ordered above other non-sticky nodes in teaser
  *     listings.
- *   - unpublished: Appears on unpublished nodes visible only to site admins.
+ *   - is-unpublished: Appears on unpublished nodes visible only to site admins.
  * - title_prefix: Additional output populated by modules, intended to be
  *   displayed in front of the main title tag that appears in the template.
  * - title_suffix: Additional output populated by modules, intended to be
@@ -75,27 +76,31 @@
  * @ingroup themeable
  */
 #}
-<article id="node-{{ node.id }}" class="{{ attributes.class }} clearfix"{{ attributes }}>
+<article class="node--{{ node.id }} {{ attributes.class }}"{{ attributes }}>
 
   {{ title_prefix }}
   {% if not page %}
     <h2{{ title_attributes }}>
-      <a href="{{ node_url }}" rel="bookmark">{{ label }}</a>
+      <a href="{{ url }}" rel="bookmark">{{ label }}</a>
     </h2>
   {% endif %}
   {{ title_suffix }}
 
-  {% if display_submitted %}
-    <footer>
-      {{ user_picture }}
-      <p class="submitted">{{ submitted }}</p>
+  {% if author or display_submitted %}
+    <footer class="node__meta">
+      {{ author }}
+      {{ submitted }}
     </footer>
   {% endif %}
 
-  <div{{ content_attributes }}>
+  <div class="node__content"{{ content_attributes }}>
     {{ content|without('links') }}
   </div>
 
-  {{ content.links }}
+  {% if content.links %}
+    <div class="node__links">
+      {{ content.links }}
+    </div>
+  {% endif %}
 
 </article>
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index bf8c60e..0d7ae2c 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -278,7 +278,7 @@ function rdf_preprocess_node(&$variables) {
   $bundle = $variables['node']->bundle();
   $mapping = rdf_get_mapping('node', $bundle);
   $bundle_mapping = $mapping->getPreparedBundleMapping('node', $bundle);
-  $variables['attributes']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url'];
+  $variables['attributes']['about'] = empty($variables['url']) ? NULL: $variables['url'];
   $variables['attributes']['typeof'] = empty($bundle_mapping['types']) ? NULL : $bundle_mapping['types'];
 
   // Adds RDFa markup for the node title as metadata because wrapping the title
@@ -322,7 +322,8 @@ function rdf_preprocess_node(&$variables) {
       $count = 0;
       foreach ($valid_fields as $field_name) {
         $count += $variables['node']->get($field_name)->comment_count;
-        // Adds RDFa markup for the comment count near the node title as metadata
+        // Adds RDFa markup for the comment count near the node title as
+        // metadata.
         $comment_count_attributes = rdf_rdfa_attributes($comment_count_mapping, $variables['node']->get($field_name)->comment_count);
         $variables['title_suffix']['rdf_meta_comment_count'] = array(
           '#theme' => 'rdf_metadata',
diff --git a/core/modules/system/css/system.theme.css b/core/modules/system/css/system.theme.css
index f397a5a..11bb596 100644
--- a/core/modules/system/css/system.theme.css
+++ b/core/modules/system/css/system.theme.css
@@ -6,10 +6,10 @@
 /**
  * Publishing status.
  */
-.unpublished {
+.is-unpublished {
   background-color: #fff4f4;
 }
-.preview {
+.is-preview {
   background-color: #ffffea;
 }
 
diff --git a/core/themes/bartik/css/style.css b/core/themes/bartik/css/style.css
index 663d60c..712fafb 100644
--- a/core/themes/bartik/css/style.css
+++ b/core/themes/bartik/css/style.css
@@ -122,7 +122,7 @@ ul.primary,
 .item-list .pager,
 div.field-type-taxonomy-term-reference,
 div.messages,
-div.meta,
+.node__meta,
 p.comment-time,
 table,
 .breadcrumb,
@@ -669,10 +669,10 @@ h1#page-title {
   font-size: 1.429em;
   line-height: 1.4;
 }
-.node .content {
+.node__content {
   font-size: 1.071em;
 }
-.view-mode-teaser .content {
+.view-mode-teaser .node__content {
   font-size: 1em;
 }
 .view-mode-teaser h2 {
@@ -693,20 +693,20 @@ h1#page-title {
   border: 1px solid #d3d7d9;
   padding: 0 15px 15px;
 }
-.view-mode-teaser .content {
+.view-mode-teaser .node__content {
   clear: none;
   line-height: 1.6;
 }
-.meta {
+.node__meta {
   font-size: 0.857em;
   color: #68696b;
   margin-bottom: -5px;
 }
-.submitted .field-name-field-user-picture img {
+.node__meta--submitted .field-name-field-user-picture img {
   float: left; /* LTR */
   margin: 1px 20px 0 0; /* LTR */
 }
-[dir="rtl"] .submitted .field-name-field-user-picture img {
+[dir="rtl"] .node__meta--submitted .field-name-field-user-picture img {
   float: right;
   margin-left: 20px;
   margin-right: 0;
@@ -745,10 +745,10 @@ h1#page-title {
   padding: 0 0 0 1em;
   float: right;
 }
-.link-wrapper {
+.node__links {
   text-align: right;
 }
-[dir="rtl"] .link-wrapper {
+[dir="rtl"] .node__links {
   text-align: left;
   margin-right: 236px;
   margin-left: 0;
diff --git a/core/themes/bartik/templates/node.html.twig b/core/themes/bartik/templates/node.html.twig
index 6afb107..af508e3 100644
--- a/core/themes/bartik/templates/node.html.twig
+++ b/core/themes/bartik/templates/node.html.twig
@@ -20,12 +20,12 @@
  *   or print a subset such as {{ content.field_example }}. Use
  *   {{ content|without('field_example') }} to exclude the printing of a
  *   given child element.
- * - user_picture: The node author's picture from user-picture.html.twig.
+ * - author: The author of this node.
  * - date: Formatted creation date. Preprocess functions can reformat it by
  *   calling format_date() with the desired parameters on
  *   $variables['created'].
  * - name: Themed username of node author output from theme_username().
- * - node_url: Direct URL of the current node.
+ * - url: Direct URL of the current node.
  * - display_submitted: Whether submission information should be displayed.
  * - submitted: Submission information created from name and date during
  *   template_preprocess_node().
@@ -38,12 +38,12 @@
  *     name will often be in a short form of the human readable label.
  *   - view-mode-[view_mode]: The View Mode of the node; for example, a teaser
  *     would result in: "view-mode-teaser", and full: "view-mode-full".
- *   - preview: Whether a node is in preview mode.
+ *   - is-preview: Whether a node is in preview mode.
  *   The following are controlled through the node publishing options.
- *   - promoted: Appears on nodes promoted to the front page.
- *   - sticky: Appears on nodes ordered above other non-sticky nodes in teaser
+ *   - is-promoted: Appears on nodes promoted to the front page.
+ *   - is-sticky: Appears on nodes ordered above other non-sticky nodes in teaser
  *     listings.
- *   - unpublished: Appears on unpublished nodes visible only to site admins.
+ *   - is-unpublished: Appears on unpublished nodes visible only to site admins.
  * - title_prefix: Additional output populated by modules, intended to be
  *   displayed in front of the main title tag that appears in the template.
  * - title_suffix: Additional output populated by modules, intended to be
@@ -69,33 +69,35 @@
  * @see template_preprocess_node()
  */
 #}
-<article id="node-{{ node.id }}" class="{{ attributes.class}} clearfix"{{ attributes }} role="article">
+<article class="node--{{ node.id }} {{ attributes.class }} clearfix"{{ attributes }}>
 
   <header>
     {{ title_prefix }}
     {% if not page %}
       <h2{{ title_attributes }}>
-        <a href="{{ node_url }}">{{ label }}</a>
+        <a href="{{ url }}" rel="bookmark">{{ label }}</a>
       </h2>
     {% endif %}
     {{ title_suffix }}
 
-    {% if display_submitted %}
-      <div class="meta submitted">
-        {{ user_picture }}
+    {% if author or display_submitted %}
+      <div class="node__meta node__meta--submitted">
+        {{ author }}
         {{ submitted }}
       </div>
     {% endif %}
   </header>
 
-  <div class="content clearfix"{{ content_attributes }}>
-    {{ content|without('links') }}
+  <div class="node__content clearfix"{{ content_attributes }}>
+    {{ content|without('comment', 'links') }}
   </div>
 
   {% if content.links %}
-    <footer class="link-wrapper">
+    <div class="node__links">
       {{ content.links }}
-    </footer>
+    </div>
   {% endif %}
 
+  {{ content.comment }}
+
 </article>
