diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 4140bbc14750f4cb8cc5826e9cb19794ff3862b4..9d98489fa572b9a65887fd17e00ae4f8b3647127 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1049,6 +1049,7 @@ function template_preprocess_table(&$variables) {
  * @see https://www.drupal.org/node/1842756
  */
 function template_preprocess_item_list(&$variables) {
+  $variables['wrapper_attributes'] = new Attribute($variables['wrapper_attributes']);
   foreach ($variables['items'] as &$item) {
     $attributes = array();
     // If the item value is an array, then it is a render array.
@@ -1752,7 +1753,7 @@ function drupal_common_theme() {
       'variables' => array('status' => MARK_NEW),
     ),
     'item_list' => array(
-      'variables' => array('items' => array(), 'title' => '', 'list_type' => 'ul', 'attributes' => array(), 'empty' => NULL, 'context' => array()),
+      'variables' => array('items' => array(), 'title' => '', 'list_type' => 'ul', 'wrapper_attributes' => array(), 'attributes' => array(), 'empty' => NULL, 'context' => array()),
     ),
     'feed_icon' => array(
       'variables' => array('url' => NULL, 'title' => NULL),
diff --git a/core/modules/datetime/src/Tests/DateTimeFieldTest.php b/core/modules/datetime/src/Tests/DateTimeFieldTest.php
index 69f3725406d2e8728446f504e3422c1443bf8a67..a2ceebde9b14055602b057deb6338ca70f43f738 100644
--- a/core/modules/datetime/src/Tests/DateTimeFieldTest.php
+++ b/core/modules/datetime/src/Tests/DateTimeFieldTest.php
@@ -589,13 +589,13 @@ function testDatelistWidget() {
   protected function datelistDataProvider() {
     return [
       // Year only selected, validation error on Month, Day, Hour, Minute.
-      [['year' => 2012, 'month' => '', 'day' => '', 'hour' => '', 'minute' => ''], '4 errors have been found:   MonthDayHourMinute'],
+      [['year' => 2012, 'month' => '', 'day' => '', 'hour' => '', 'minute' => ''], '4 errors have been found: MonthDayHourMinute'],
       // Year and Month selected, validation error on Day, Hour, Minute.
-      [['year' => 2012, 'month' => '12', 'day' => '', 'hour' => '', 'minute' => ''], '3 errors have been found:   DayHourMinute'],
+      [['year' => 2012, 'month' => '12', 'day' => '', 'hour' => '', 'minute' => ''], '3 errors have been found: DayHourMinute'],
       // Year, Month and Day selected, validation error on Hour, Minute.
-      [['year' => 2012, 'month' => '12', 'day' => '31', 'hour' => '', 'minute' => ''], '2 errors have been found:   HourMinute'],
+      [['year' => 2012, 'month' => '12', 'day' => '31', 'hour' => '', 'minute' => ''], '2 errors have been found: HourMinute'],
       // Year, Month, Day and Hour selected, validation error on Minute only.
-      [['year' => 2012, 'month' => '12', 'day' => '31', 'hour' => '0', 'minute' => ''], '1 error has been found:   Minute'],
+      [['year' => 2012, 'month' => '12', 'day' => '31', 'hour' => '0', 'minute' => ''], '1 error has been found: Minute'],
     ];
   }
 
diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php
index 2b341b875a6f541290db15599b7052a88a53e4e3..8d5e15b65c078bf21cf6354c5931727b4a640a52 100644
--- a/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php
+++ b/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php
@@ -275,7 +275,7 @@ public function testFieldAdminHandler() {
     $this->drupalPostForm('node/add/' . $this->type, $edit, t('Save'));
 
     // Assert that entity reference autocomplete field is validated.
-    $this->assertText(t('1 error has been found:   Test Entity Reference Field'), 'Node save failed when required entity reference field was not correctly filled.');
+    $this->assertText(t('1 error has been found: Test Entity Reference Field'), 'Node save failed when required entity reference field was not correctly filled.');
     $this->assertText(t('There are no entities matching "@entity"', ['@entity' => 'Test']));
 
     $edit = array(
@@ -286,7 +286,7 @@ public function testFieldAdminHandler() {
 
     // Assert the results multiple times to avoid sorting problem of nodes with
     // the same title.
-    $this->assertText(t('1 error has been found:   Test Entity Reference Field'));
+    $this->assertText(t('1 error has been found: Test Entity Reference Field'));
     $this->assertText(t('Multiple entities match this reference;'));
     $this->assertText(t("@node1", ['@node1' => $node1->getTitle() . ' (' . $node1->id() . ')']));
     $this->assertText(t("@node2", ['@node2' => $node2->getTitle() . ' (' . $node2->id() . ')']));
diff --git a/core/modules/file/src/Tests/FileFieldValidateTest.php b/core/modules/file/src/Tests/FileFieldValidateTest.php
index ab1d2a5a82e5c015da2c0fcde3050edc2df916b8..89bac43c26ba74c3989c8f4acec28cacf048abbc 100644
--- a/core/modules/file/src/Tests/FileFieldValidateTest.php
+++ b/core/modules/file/src/Tests/FileFieldValidateTest.php
@@ -35,7 +35,7 @@ function testRequired() {
     $edit = array();
     $edit['title[0][value]'] = $this->randomMachineName();
     $this->drupalPostForm('node/add/' . $type_name, $edit, t('Save and publish'));
-    $this->assertText('1 error has been found:   ' . $field->label(), 'Node save failed when required file field was empty.');
+    $this->assertText('1 error has been found: ' . $field->label(), 'Node save failed when required file field was empty.');
     $this->assertIdentical(1, count($this->xpath('//div[contains(concat(" ", normalize-space(@class), " "), :class)]//a', [':class' => ' messages--error '])), 'There is one link in the error message.');
 
     // Create a new node with the uploaded file.
@@ -57,7 +57,7 @@ function testRequired() {
     $edit = array();
     $edit['title[0][value]'] = $this->randomMachineName();
     $this->drupalPostForm('node/add/' . $type_name, $edit, t('Save and publish'));
-    $this->assertText('1 error has been found:   '  . $field->label(), 'Node save failed when required multiple value file field was empty.');
+    $this->assertText('1 error has been found: ' . $field->label(), 'Node save failed when required multiple value file field was empty.');
     $this->assertIdentical(1, count($this->xpath('//div[contains(concat(" ", normalize-space(@class), " "), :class)]//a', [':class' => ' messages--error '])), 'There is one link in the error message.');
 
     // Create a new node with the uploaded file into the multivalue field.
diff --git a/core/modules/system/css/components/item-list.module.css b/core/modules/system/css/components/item-list.module.css
new file mode 100644
index 0000000000000000000000000000000000000000..7bddff9e768b4fe0aab4057b1305972996d60a84
--- /dev/null
+++ b/core/modules/system/css/components/item-list.module.css
@@ -0,0 +1,19 @@
+/**
+ * @file
+ * Styles for item list.
+ */
+
+.item-list__comma-list,
+.item-list__comma-list li {
+  display: inline;
+}
+.item-list__comma-list {
+  margin: 0;
+  padding: 0;
+}
+.item-list__comma-list li:after {
+  content: ", ";
+}
+.item-list__comma-list li:last-child:after {
+  content: "";
+}
diff --git a/core/modules/system/system.libraries.yml b/core/modules/system/system.libraries.yml
index 4a3bae6e4ca591109760024548b54f1f2f1c6f0a..dd9d2ec43ecc3d758e0aa8fb8ce73153b7949a29 100644
--- a/core/modules/system/system.libraries.yml
+++ b/core/modules/system/system.libraries.yml
@@ -11,6 +11,7 @@ base:
       css/components/clearfix.module.css: { weight: -10 }
       css/components/details.module.css: { weight: -10 }
       css/components/hidden.module.css: { weight: -10 }
+      css/components/item-list.module.css: { weight: -10 }
       css/components/js.module.css: { weight: -10 }
       css/components/nowrap.module.css: { weight: -10 }
       css/components/position-container.module.css: { weight: -10 }
diff --git a/core/modules/system/templates/item-list.html.twig b/core/modules/system/templates/item-list.html.twig
index 172799d8f1d8ba0895c019c5850e4c32371d1b95..1462cf41ae0fddc9dab0380f95ac69de07184209 100644
--- a/core/modules/system/templates/item-list.html.twig
+++ b/core/modules/system/templates/item-list.html.twig
@@ -9,6 +9,7 @@
  *   - value: The content of the list element.
  * - title: The title of the list.
  * - list_type: The tag for list element ("ul" or "ol").
+ * - wrapper_attributes: HTML attributes to be applied to the list wrapper.
  * - attributes: HTML attributes to be applied to the list.
  * - empty: A message to display when there are no items. Allowed value is a
  *   string or render array.
@@ -21,9 +22,9 @@
  */
 #}
 {% if context.list_style %}
-  {% set attributes = attributes.addClass('item-list__' ~ context.list_style) %}
+  {%- set attributes = attributes.addClass('item-list__' ~ context.list_style) %}
 {% endif %}
-{%- if items or empty -%}
+{% if items or empty %}
   {%- if title is not empty -%}
     <h3>{{ title }}</h3>
   {%- endif -%}
diff --git a/core/themes/bartik/css/components/item-list.css b/core/themes/bartik/css/components/item-list.css
index 943aef2dd8d57d7952019ceb2f04d369a4fde4da..51a69c8c4c09dab19a2d55e0192f6f8188224897 100644
--- a/core/themes/bartik/css/components/item-list.css
+++ b/core/themes/bartik/css/components/item-list.css
@@ -25,6 +25,5 @@
 .item-list .item-list__comma-list li,
 [dir="rtl"] .item-list .item-list__comma-list,
 [dir="rtl"] .item-list .item-list__comma-list li {
-  margin: 0;
   padding: 0;
 }
diff --git a/core/themes/classy/css/components/item-list.css b/core/themes/classy/css/components/item-list.css
index 9a1088e062d5f69bd82bfff3a125ce1f46681216..a8ce5d28a53ddd7de538b7f83983dcbaa359b817 100644
--- a/core/themes/classy/css/components/item-list.css
+++ b/core/themes/classy/css/components/item-list.css
@@ -10,30 +10,23 @@
   margin: 0 0 0.75em 0;
   padding: 0;
 }
-.item-list ul li {
+.item-list li {
   margin: 0 0 0.25em 1.5em; /* LTR */
   padding: 0;
 }
-[dir="rtl"] .item-list ul li {
+[dir="rtl"] .item-list li {
   margin: 0 1.5em 0.25em 0;
 }
-ul.item-list__comma-list {
-  display: inline;
-}
-ul.item-list__comma-list li {
+
+/**
+ * Comma separated lists.
+ */
+.item-list--comma-list {
   display: inline;
-  list-style-type: none;
 }
-ul.item-list__comma-list,
-ul.item-list__comma-list li,
-[dir="rtl"] ul.item-list__comma-list,
-[dir="rtl"] ul.item-list__comma-list li {
+.item-list--comma-list .item-list__comma-list,
+.item-list__comma-list li,
+[dir="rtl"] .item-list--comma-list .item-list__comma-list,
+[dir="rtl"] .item-list__comma-list li {
   margin: 0;
-  padding: 0;
-}
-ul.item-list__comma-list li:after {
-  content: ", ";
-}
-ul.item-list__comma-list li:last-child:after {
-  content: "";
 }
diff --git a/core/themes/classy/templates/dataset/item-list.html.twig b/core/themes/classy/templates/dataset/item-list.html.twig
index 7ba8be4910decf1c67b00bff048d29c415c26caa..20541b0b7e6652761504f747ad9972a2759fe27b 100644
--- a/core/themes/classy/templates/dataset/item-list.html.twig
+++ b/core/themes/classy/templates/dataset/item-list.html.twig
@@ -9,6 +9,7 @@
  *   - value: The content of the list element.
  * - title: The title of the list.
  * - list_type: The tag for list element ("ul" or "ol").
+ * - wrapper_attributes: HTML attributes to be applied to the list wrapper.
  * - attributes: HTML attributes to be applied to the list.
  * - empty: A message to display when there are no items. Allowed value is a
  *   string or render array.
@@ -19,10 +20,11 @@
  */
 #}
 {% if context.list_style %}
-  {% set attributes = attributes.addClass('item-list__' ~ context.list_style) %}
+  {%- set wrapper_attributes = wrapper_attributes.addClass('item-list--' ~ context.list_style) %}
+  {%- set attributes = attributes.addClass('item-list__' ~ context.list_style) %}
 {% endif %}
-{%- if items or empty -%}
-  <div class="item-list">
+{% if items or empty -%}
+  <div{{ wrapper_attributes.addClass('item-list') }}>
     {%- if title is not empty -%}
       <h3>{{ title }}</h3>
     {%- endif -%}
diff --git a/core/themes/seven/css/components/menus-and-lists.css b/core/themes/seven/css/components/menus-and-lists.css
index 0dc37a65e264f8b713d09b597565c9c2ec912ca2..d96fe5516b82f286998443a33f9d278da31df6c4 100644
--- a/core/themes/seven/css/components/menus-and-lists.css
+++ b/core/themes/seven/css/components/menus-and-lists.css
@@ -38,7 +38,3 @@ ul.inline li {
 ul.inline li {
   display: inline;
 }
-.item-list .item-list__comma-list,
-[dir="rtl"] .item-list .item-list__comma-list {
-  margin: 0;
-}