diff --git a/core/lib/Drupal/Core/Template/Attribute.php b/core/lib/Drupal/Core/Template/Attribute.php
index 48e2fa1..7372c63 100644
--- a/core/lib/Drupal/Core/Template/Attribute.php
+++ b/core/lib/Drupal/Core/Template/Attribute.php
@@ -80,8 +80,18 @@ public function offsetSet($name, $value) {
    *   An AttributeValueBase representation of the attribute's value.
    */
   protected function createAttributeValue($name, $value) {
-    if (is_array($value)) {
-      $value = new AttributeArray($name, $value);
+    // If the value is already an AttributeValueBase object, return it
+    // straight away.
+    if ($value instanceOf AttributeValueBase) {
+      return $value;
+    }
+    // An array value or 'class' attribute name are forced to always be an
+    // AttributeArray value for consistency.
+    if (is_array($value) || $name == 'class') {
+      // Cast the value to an array if the value was passed in as a string.
+      // @todo Decide to fix all the broken instances of class as a string
+      // in core or cast them.
+      $value = new AttributeArray($name, (array) $value);
     }
     elseif (is_bool($value)) {
       $value = new AttributeBoolean($name, $value);
@@ -107,6 +117,70 @@ public function offsetExists($name) {
   }
 
   /**
+   * Adds the argument values by merging them on to the value array.
+   *
+   * @param mixed ...
+   *   Classes arguments to add.
+   *
+   * @return $this
+   */
+  public function addClass() {
+    $args = func_get_args();
+    $classes = array();
+    foreach ($args as $arg) {
+      // Merge the values passed in from the classes array.
+      // The argument is cast to an array to support comma separated single
+      // values or one or more array arguments.
+      $classes = array_merge($classes, (array) $arg);
+    }
+
+    // Merge if there are values, just add them otherwise.
+    if (isset($this->storage['class']) && $this->storage['class'] instanceOf AttributeArray) {
+      // Merge the values passed in from the class value array.
+      $classes = array_merge($this->storage['class']->value(), $classes);
+      // Filter out any empty values.
+      $classes = array_filter($classes);
+      $this->storage['class']->exchangeArray($classes);
+    }
+    else {
+      // Filter out any empty values.
+      $classes = array_filter($classes);
+      $this->offsetSet('class', $classes);
+    }
+
+    return $this;
+  }
+
+  /**
+   * Removes the argument values from the value array.
+   *
+   * @param mixed ...
+   *   Classes arguments to remove.
+   *
+   * @return $this
+   */
+  public function removeClass() {
+    // With no class attribute, there is no need to remove.
+    if (isset($this->storage['class']) && $this->storage['class'] instanceOf AttributeArray) {
+      $args = func_get_args();
+      $classes = array();
+      foreach ($args as $arg) {
+        // Merge the values passed in from the classes array.
+        // The argument is cast to an array to support comma separated single
+        // values or one or more array arguments.
+        $classes = array_merge($classes, (array) $arg);
+      }
+
+      // Remove the values passed in from the value array.
+      $classes = array_diff($this->storage['class']->value(), $classes);
+      // Filter out any empty values.
+      $classes = array_filter($classes);
+      $this->storage['class']->exchangeArray($classes);
+    }
+    return $this;
+  }
+
+  /**
    * Implements the magic __toString() method.
    */
   public function __toString() {
diff --git a/core/lib/Drupal/Core/Template/AttributeArray.php b/core/lib/Drupal/Core/Template/AttributeArray.php
index 95e0ef3..c432ba0 100644
--- a/core/lib/Drupal/Core/Template/AttributeArray.php
+++ b/core/lib/Drupal/Core/Template/AttributeArray.php
@@ -83,4 +83,21 @@ public function value() {
     return $this->value;
   }
 
+  /**
+   * Exchange the array for another one.
+   *
+   * @see ArrayObject::exchangeArray
+   *
+   * @param array $input
+   *   The array input to replace the internal value.
+   *
+   * @return array
+   *   The old array value.
+   */
+  public function exchangeArray($input) {
+    $old = $this->value;
+    $this->value = $input;
+    return $old;
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
index aee1dd7..0a9859d 100644
--- a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
+++ b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
@@ -58,6 +58,126 @@ public function testRemove() {
   }
 
   /**
+   * Tests adding class attributes with the AttributeArray helper method.
+   * @covers ::addClass()
+   */
+  public function testAddClasses() {
+    // Add empty Attribute object with no classes.
+    $attribute = new Attribute();
+
+    // Add one class on empty attribute.
+    $attribute->addClass('banana');
+    $this->assertArrayEquals(array('banana'), $attribute['class']->value());
+
+    // Add one class.
+    $attribute->addClass('aa');
+    $this->assertArrayEquals(array('banana', 'aa'), $attribute['class']->value());
+
+    // Add multiple classes.
+    $attribute->addClass('xx', 'yy');
+    $this->assertArrayEquals(array('banana', 'aa', 'xx', 'yy'), $attribute['class']->value());
+
+    // Add an array of classes.
+    $attribute->addClass(array('red', 'green', 'blue'));
+    $this->assertArrayEquals(array('banana', 'aa', 'xx', 'yy', 'red', 'green', 'blue'), $attribute['class']->value());
+  }
+
+  /**
+   * Tests removing class attributes with the AttributeArray helper method.
+   * @covers ::removeClass()
+   */
+  public function testRemoveClasses() {
+    $classes = array('example-class', 'aa', 'xx', 'yy', 'red', 'green', 'blue');
+    $attribute = new Attribute(array('class' => $classes));
+
+    // Remove one class.
+    $attribute->removeClass('example-class');
+    $this->assertNotContains('example-class', $attribute['class']->value());
+
+    // Remove multiple classes.
+    $attribute->removeClass('xx', 'yy');
+    $this->assertNotContains(array('xx', 'yy'), $attribute['class']->value());
+
+    // Remove an array of classes.
+    $attribute->removeClass(array('red', 'green', 'blue'));
+    $this->assertNotContains(array('red', 'green', 'blue'), $attribute['class']->value());
+  }
+
+  /**
+   * Tests removing class attributes with the Attribute helper methods.
+   * @covers ::removeClass()
+   * @covers ::addClass()
+   */
+  public function testChainAddRemoveClasses() {
+    $attribute = new Attribute(
+      array('class' => array('example-class', 'red', 'green', 'blue'))
+    );
+
+    $attribute
+      ->removeClass(array('red', 'green', 'pink'))
+      ->addClass(array('apple', 'lime', 'grapefruit'))
+      ->addClass(array('banana'));
+    $expected = array('example-class', 'blue', 'apple', 'lime', 'grapefruit', 'banana');
+    $this->assertArrayEquals($expected, $attribute['class']->value(), 'Attributes chained');
+  }
+
+  /**
+   * Tests the twig calls to the Attribute.
+   * @dataProvider providerTestAttributeClassHelpers
+   *
+   * @covers ::removeClass()
+   * @covers ::addClass()
+   */
+  public function testTwigAddRemoveClasses($template, $expected, $seed_attributes = array()) {
+    $loader = new \Twig_Loader_String();
+    $twig = new \Twig_Environment($loader);
+    $data = array('attributes' => new Attribute($seed_attributes));
+    $result = $twig->render($template, $data);
+    $this->assertEquals($expected, $result);
+  }
+
+  /**
+   * Provides tests data for testEscaping
+   *
+   * @return array
+   *   An array of test data each containing of a twig template string,
+   *   a resulting string of classes and an optional array of attributes.
+   */
+  public function providerTestAttributeClassHelpers() {
+    return array(
+      array("{{ attributes.class }}", ''),
+      array("{{ attributes.addClass('everest').class }}", 'everest'),
+      array("{{ attributes.addClass(['k2', 'kangchenjunga']).class }}", 'k2 kangchenjunga'),
+      array("{{ attributes.addClass('lhotse', 'makalu', 'cho-oyu').class }}", 'lhotse makalu cho-oyu'),
+      array(
+        "{{ attributes.addClass('nanga-parbat').class }}",
+        'dhaulagiri manaslu nanga-parbat',
+        array('class' => array('dhaulagiri', 'manaslu')),
+      ),
+      array(
+        "{{ attributes.removeClass('annapurna').class }}",
+        'gasherbrum-i',
+        array('class' => array('annapurna', 'gasherbrum-i')),
+      ),
+      array(
+        "{{ attributes.removeClass(['broad peak']).class }}",
+        'gasherbrum-ii',
+        array('class' => array('broad peak', 'gasherbrum-ii')),
+      ),
+      array(
+        "{{ attributes.removeClass('gyachung-kang', 'shishapangma').class }}",
+        '',
+        array('class' => array('shishapangma', 'gyachung-kang')),
+      ),
+      array(
+        "{{ attributes.removeClass('nuptse').addClass('annapurna-ii').class }}",
+        'himalchuli annapurna-ii',
+        array('class' => array('himalchuli', 'nuptse')),
+      ),
+    );
+  }
+
+  /**
    * Tests iterating on the values of the attribute.
    */
   public function testIterate() {
