diff --git a/core/lib/Drupal/Core/Asset/AssetResolver.php b/core/lib/Drupal/Core/Asset/AssetResolver.php
index 6186d2a..9927049 100644
--- a/core/lib/Drupal/Core/Asset/AssetResolver.php
+++ b/core/lib/Drupal/Core/Asset/AssetResolver.php
@@ -166,6 +166,7 @@ public function getCssAssets(AttachedAssetsInterface $assets, $optimize) {
     uasort($css, 'static::sort');
 
     // Allow themes to remove CSS files by CSS files full path and file name.
+    // @todo Remove in Drupal 9.0.x.
     if ($stylesheet_remove = $theme_info->getStyleSheetsRemove()) {
       foreach ($css as $key => $options) {
         if (isset($stylesheet_remove[$key])) {
diff --git a/core/lib/Drupal/Core/Asset/Exception/InvalidLibrariesExtendSpecificationException.php b/core/lib/Drupal/Core/Asset/Exception/InvalidLibrariesExtendSpecificationException.php
new file mode 100644
index 0000000..f1b9df0
--- /dev/null
+++ b/core/lib/Drupal/Core/Asset/Exception/InvalidLibrariesExtendSpecificationException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException.
+ */
+
+namespace Drupal\Core\Asset\Exception;
+
+/**
+ * Defines a custom exception for an invalid libraries-extend specification.
+ */
+class InvalidLibrariesExtendSpecificationException extends \RuntimeException {
+
+}
diff --git a/core/lib/Drupal/Core/Asset/Exception/InvalidLibrariesOverrideSpecificationException.php b/core/lib/Drupal/Core/Asset/Exception/InvalidLibrariesOverrideSpecificationException.php
new file mode 100644
index 0000000..89667aa
--- /dev/null
+++ b/core/lib/Drupal/Core/Asset/Exception/InvalidLibrariesOverrideSpecificationException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException.
+ */
+
+namespace Drupal\Core\Asset\Exception;
+
+/**
+ * Defines a custom exception if a definition refers to a non-existent library.
+ */
+class InvalidLibrariesOverrideSpecificationException extends \RuntimeException {
+
+}
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php b/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
index 6dd83f7..9b5c6e8 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscovery.php
@@ -9,8 +9,6 @@
 
 use Drupal\Core\Cache\CacheCollectorInterface;
 use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Theme\ThemeManagerInterface;
 
 /**
  * Discovers available asset libraries in Drupal.
@@ -87,6 +85,8 @@ public function getLibraryByName($extension, $name) {
    */
   public function clearCachedDefinitions() {
     $this->cacheTagInvalidator->invalidateTags(['library_info']);
+    $this->libraryDefinitions = [];
+    $this->collector->clear();
   }
 
 }
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php
index 7ab83d5..f7dc640 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php
@@ -7,6 +7,9 @@
 
 namespace Drupal\Core\Asset;
 
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException;
+use Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException;
 use Drupal\Core\Cache\CacheCollector;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Lock\LockBackendInterface;
@@ -79,9 +82,94 @@ protected function getCid() {
    * {@inheritdoc}
    */
   protected function resolveCacheMiss($key) {
-    $this->storage[$key] = $this->discoveryParser->buildByExtension($key);
+    $this->storage[$key] = $this->getLibraryDefinitions($key);
     $this->persist($key);
 
     return $this->storage[$key];
   }
+
+
+  /**
+   * Returns the library definitions for a given extension.
+   *
+   * This also implements libraries-overrides for entire libraries that have
+   * been specified by the LibraryDiscoveryParser.
+   *
+   * @param string $extension
+   *   The name of the extension for which library definitions will be returned.
+   *
+   * @return array
+   *   The library definitions for $extension with overrides applied.
+   *
+   * @throws \Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException
+   */
+  protected function getLibraryDefinitions($extension) {
+    $libraries = $this->discoveryParser->buildByExtension($extension);
+    foreach ($libraries as $name => $definition) {
+      // Handle libraries that are marked for override or removal.
+      // @see \Drupal\Core\Asset\LibraryDiscoveryParser::applyLibrariesOverride()
+      if (isset($definition['override'])) {
+        if ($definition['override'] === FALSE) {
+          // Remove the library definition if FALSE is given.
+          unset($libraries[$name]);
+        }
+        else {
+          // Otherwise replace with existing library definition if it exists.
+          // Throw an exception if it doesn't.
+          list($replacement_extension, $replacement_name) = explode('/', $definition['override']);
+          $replacement_definition = $this->get($replacement_extension);
+          if (isset($replacement_definition[$replacement_name])) {
+            $libraries[$name] = $replacement_definition[$replacement_name];
+          }
+          else {
+            throw new InvalidLibrariesOverrideSpecificationException(sprintf('The specified library %s does not exist.', $definition['override']));
+          }
+        }
+      }
+      else {
+        // Apply libraries extend.
+        $libraries[$name] = $this->applyLibrariesExtend($extension, $name, $definition);
+      }
+    }
+    return $libraries;
+  }
+
+  /**
+   * Applies the libraries-extend specified by the active theme.
+   *
+   * This extends the library definitions with the those specified by the
+   * libraries-extend specifications for the active theme.
+   *
+   * @param string $extension
+   *   The name of the extension for which library definitions will be extended.
+   * @param string $library_name
+   *   The name of the library whose definitions is to be extended.
+   * @param $library_definition
+   *   The library definition to be extended.
+   *
+   * @return array
+   *   The library definition extended as specified by libraries-extend.
+   *
+   * @throws \Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException
+   */
+  protected function applyLibrariesExtend($extension, $library_name, $library_definition) {
+    $active_theme = $this->themeManager->getActiveTheme()->getLibrariesExtend();
+    if (!empty($active_theme["$extension/$library_name"])) {
+      foreach ($active_theme["$extension/$library_name"] as $library_extend_name) {
+        if (!is_string($library_extend_name)) {
+          // Only string library names are allowed.
+          throw new InvalidLibrariesExtendSpecificationException('The libraries-extend specification must be a string.');
+        }
+        list($new_extension, $new_library_name) = explode('/', $library_extend_name, 2);
+        $new_libraries = $this->get($new_extension);
+        if (isset($new_libraries[$new_library_name])) {
+          $library_definition = NestedArray::mergeDeep($library_definition, $new_libraries[$new_library_name]);
+        }
+        else {
+          throw new InvalidLibrariesExtendSpecificationException(sprintf('The specified library %s does not exist.', $library_extend_name));
+        }
+      }
+    }
+    return $library_definition;
+  }
 }
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
index e6a4376..427640f 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
@@ -8,8 +8,10 @@
 namespace Drupal\Core\Asset;
 
 use Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException;
+use Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException;
 use Drupal\Core\Asset\Exception\InvalidLibraryFileException;
 use Drupal\Core\Asset\Exception\LibraryDefinitionMissingLicenseException;
+use Drupal\Core\Extension\Extension;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Theme\ThemeManagerInterface;
 use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
@@ -88,6 +90,7 @@ public function buildByExtension($extension) {
     }
 
     $libraries = $this->parseLibraryInfo($extension, $path);
+    $libraries = $this->applyLibrariesOverride($libraries, $extension);
 
     foreach ($libraries as $id => &$library) {
       if (!isset($library['js']) && !isset($library['css']) && !isset($library['drupalSettings'])) {
@@ -185,6 +188,13 @@ public function buildByExtension($extension) {
             elseif ($this->fileValidUri($source)) {
               $options['data'] = $source;
             }
+            // A regular URI (e.g., http://example.com/example.js) without
+            // 'external' explicitly specified, which may happen if, e.g.
+            // libraries-override is used.
+            elseif ($this->isValidUri($source)) {
+              $options['type'] = 'external';
+              $options['data'] = $source;
+            }
             // By default, file paths are relative to the registering extension.
             else {
               $options['data'] = $path . '/' . $source;
@@ -314,6 +324,70 @@ protected function parseLibraryInfo($extension, $path) {
   }
 
   /**
+   * Apply libraries overrides specified for the current active theme.
+   *
+   * @param array $libraries
+   *   The libraries definitions.
+   * @param string $extension
+   *   The extension in which these libraries are defined.
+   *
+   * @return array
+   *   The modified libraries definitions.
+   */
+  protected function applyLibrariesOverride($libraries, $extension) {
+    $active_theme = $this->themeManager->getActiveTheme();
+    // ActiveTheme::getLibrariesOverride() returns libraries-overrides for the
+    // current theme as well as all its base themes.
+    $all_libraries_overrides = $active_theme->getLibrariesOverride();
+    foreach ($all_libraries_overrides as $theme_path => $libraries_overrides) {
+      foreach ($libraries as $library_name => $library) {
+        // Process libraries overrides.
+        if (isset($libraries_overrides["$extension/$library_name"])) {
+          // Active theme defines an override for this library.
+          $override_definition = $libraries_overrides["$extension/$library_name"];
+          if (is_string($override_definition) || $override_definition === FALSE) {
+            // A string or boolean definition implies an override (or removal)
+            // for the whole library. Use the override key to specify that this
+            // library will be overridden when it is called.
+            // @see \Drupal\Core\Asset\LibraryDiscovery::getLibraryByName()
+            if ($override_definition) {
+              $libraries[$library_name]['override'] = $override_definition;
+            }
+            else {
+              $libraries[$library_name]['override'] = FALSE;
+            }
+          }
+          elseif (is_array($override_definition)) {
+            // An array definition implies an override for an asset within this
+            // library.
+            foreach ($override_definition as $sub_key => $value) {
+              // Throw an exception if the asset is not properly specified.
+              if (!is_array($value)) {
+                throw new InvalidLibrariesOverrideSpecificationException(sprintf('Library asset %s is not correctly specified. It should be in the form "extension/library_name/sub_key/path/to/asset.js".', "$extension/$library_name/$sub_key"));
+              }
+              if ($sub_key === 'drupalSettings') {
+                // drupalSettings may not be overridden.
+                throw new InvalidLibrariesOverrideSpecificationException(sprintf('drupalSettings may not be overridden in libraries-override. Trying to override %s. Use hook_library_info_alter() instead.', "$extension/$library_name/$sub_key"));
+              }
+              elseif ($sub_key === 'css') {
+                // SMACSS category should be incorporated into the asset name.
+                foreach ($value as $category => $overrides) {
+                  $this->setOverrideValue($libraries[$library_name], [$sub_key, $category], $overrides, $theme_path);
+                }
+              }
+              else {
+                $this->setOverrideValue($libraries[$library_name], [$sub_key], $value, $theme_path);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return $libraries;
+  }
+
+  /**
    * Wraps drupal_get_path().
    */
   protected function drupalGetPath($type, $name) {
@@ -327,4 +401,67 @@ protected function fileValidUri($source) {
     return file_valid_uri($source);
   }
 
+  /**
+   * Determines if the supplied string is a valid URI.
+   */
+  protected function isValidUri($string) {
+    return count(explode('://', $string)) === 2;
+  }
+
+  /**
+   * Overrides the specified library asset.
+   *
+   * @param array $library
+   *   The containing library definition.
+   * @param array $sub_key
+   *   An array containing the sub-keys specifying the library asset, e.g.
+   *   @code['js']@endcode or @code['css', 'component']@endcode
+   * @param array $overrides
+   *   Specifies the overrides, this is an array where the key is the asset to
+   *   be overridden while the value is overriding asset.
+   */
+  protected function setOverrideValue(array &$library, array $sub_key, array $overrides, $theme_path) {
+    foreach ($overrides as $original => $replacement) {
+      // Get the attributes of the asset to be overridden. If the key does
+      // not exist, then throw an exception.
+      $key_exists = NULL;
+      $parents = array_merge($sub_key, [$original]);
+      // Save the attributes of the library asset to be overridden.
+      $attributes = NestedArray::getValue($library, $parents, $key_exists);
+      if ($key_exists) {
+        // Remove asset to be overridden.
+        NestedArray::unsetValue($library, $parents);
+        // No need to replace if FALSE is specified, since that is a removal.
+        if ($replacement) {
+          // Ensure the replacement path is relative to drupal root.
+          $replacement = $this->resolveThemeAssetPath($theme_path, $replacement);
+          $new_parents = array_merge($sub_key, [$replacement]);
+          // Replace with an override if specified.
+          NestedArray::setValue($library, $new_parents, $attributes);
+        }
+      }
+    }
+  }
+
+  /**
+   * Ensures that a full path is returned for an overriding theme asset.
+   *
+   * @param string $theme_path
+   *   The theme or base theme.
+   * @param string $overriding_asset
+   *   The overriding library asset.
+   *
+   * @return string
+   *   A fully resolved theme asset path relative to the Drupal directory.
+   */
+  protected function resolveThemeAssetPath($theme_path, $overriding_asset) {
+    if ($overriding_asset[0] !== '/' && !$this->isValidUri($overriding_asset)) {
+      // The destination is not an absolute path and it's not a URI (e.g.
+      // public://generated_js/example.js or http://example.com/js/my_js.js), so
+      // it's relative to the theme.
+      return '/' . $theme_path . '/' . $overriding_asset;
+    }
+    return $overriding_asset;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Theme/ActiveTheme.php b/core/lib/Drupal/Core/Theme/ActiveTheme.php
index c35afad..3b43cc0 100644
--- a/core/lib/Drupal/Core/Theme/ActiveTheme.php
+++ b/core/lib/Drupal/Core/Theme/ActiveTheme.php
@@ -81,6 +81,13 @@ class ActiveTheme {
   protected $regions;
 
   /**
+   * The libraries or library assets overridden by the theme.
+   *
+   * @var array
+   */
+  protected $librariesOverride;
+
+  /**
    * Constructs an ActiveTheme object.
    *
    * @param array $values
@@ -96,6 +103,8 @@ public function __construct(array $values) {
       'extension' => 'html.twig',
       'base_themes' => [],
       'regions' => [],
+      'libraries_override' => [],
+      'libraries_extend' => [],
     ];
 
     $this->name = $values['name'];
@@ -107,6 +116,8 @@ public function __construct(array $values) {
     $this->extension = $values['extension'];
     $this->baseThemes = $values['base_themes'];
     $this->regions = $values['regions'];
+    $this->librariesOverride = $values['libraries_override'];
+    $this->librariesExtend = $values['libraries_extend'];
   }
 
   /**
@@ -169,6 +180,8 @@ public function getLibraries() {
    * Returns the removed stylesheets by the theme.
    *
    * @return mixed
+   *
+   * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.
    */
   public function getStyleSheetsRemove() {
     return $this->styleSheetsRemove;
@@ -198,4 +211,24 @@ public function getRegions() {
     return array_keys($this->regions);
   }
 
+  /**
+   * Returns the libraries or library assets overridden by the active theme.
+   *
+   * @return array
+   *   The list of libraries overrides.
+   */
+  public function getLibrariesOverride() {
+    return $this->librariesOverride;
+  }
+
+  /**
+   * Returns the libraries extended by the active theme.
+   *
+   * @return array
+   *   The list of libraries extend.
+   */
+  public function getLibrariesExtend() {
+    return $this->librariesExtend;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Theme/ThemeInitialization.php b/core/lib/Drupal/Core/Theme/ThemeInitialization.php
index 8b476a2..e9bae2d 100644
--- a/core/lib/Drupal/Core/Theme/ThemeInitialization.php
+++ b/core/lib/Drupal/Core/Theme/ThemeInitialization.php
@@ -161,27 +161,42 @@ public function getActiveTheme(Extension $theme, array $base_themes = []) {
     $values['path'] = $theme_path;
     $values['name'] = $theme->getName();
 
-    // Prepare stylesheets from this theme as well as all ancestor themes.
-    // We work it this way so that we can have child themes remove CSS files
-    // easily from parent.
-    $values['stylesheets_remove'] = array();
+    // @todo Remove in Drupal 9.0.x.
+    $values['stylesheets_remove'] = $this->prepareStylesheetsRemove($theme, $base_themes);
 
-    // Grab stylesheets from base theme.
+    // Prepare libraries overrides from this theme and ancestor themes. This
+    // allows child themes to easily remove CSS files from base themes and
+    // modules.
+    $values['libraries_override'] = [];
+
+    // Get libraries overrides declared by base themes.
     foreach ($base_themes as $base) {
-      $base_theme_path = $base->getPath();
-      if (!empty($base->info['stylesheets-remove'])) {
-        foreach ($base->info['stylesheets-remove'] as $css_file) {
-          $css_file = $this->resolveStyleSheetPlaceholders($css_file);
-          $values['stylesheets_remove'][$css_file] = $css_file;
+      if (!empty($base->info['libraries-override'])) {
+        foreach ($base->info['libraries-override'] as $library => $override) {
+          $values['libraries_override'][$base->getPath()][$library] = $override;
         }
       }
     }
 
-    // Add stylesheets used by this theme.
-    if (!empty($theme->info['stylesheets-remove'])) {
-      foreach ($theme->info['stylesheets-remove'] as $css_file) {
-        $css_file = $this->resolveStyleSheetPlaceholders($css_file);
-        $values['stylesheets_remove'][$css_file] = $css_file;
+    // Add libraries overrides declared by this theme.
+    if (!empty($theme->info['libraries-override'])) {
+      foreach ($theme->info['libraries-override'] as $library => $override) {
+        $values['libraries_override'][$theme->getPath()][$library] = $override;
+      }
+    }
+
+    // Get libraries extend declared by base themes.
+    foreach ($base_themes as $base) {
+      if (!empty($base->info['libraries-extend'])) {
+        foreach ($base->info['libraries-extend'] as $library => $extend) {
+          $values['libraries_extend'][$library] = $extend;
+        }
+      }
+    }
+    // Add libraries extend declared by this theme.
+    if (!empty($theme->info['libraries-extend'])) {
+      foreach ($theme->info['libraries-extend'] as $library => $extend) {
+        $values['libraries_extend'][$library] = $extend;
       }
     }
 
@@ -241,6 +256,8 @@ protected function getExtensions() {
    *
    * @return string
    *   CSS file where placeholders are replaced.
+   *
+   * @todo Remove in Drupal 9.0.x.
    */
   protected function resolveStyleSheetPlaceholders($css_file) {
     $token_candidate = explode('/', $css_file)[0];
@@ -256,4 +273,44 @@ protected function resolveStyleSheetPlaceholders($css_file) {
       return str_replace($token_candidate, $extensions[$token]->getPath(), $css_file);
     }
   }
+
+  /**
+   * Prepares stylesheets-remove specified in the *.info.yml file.
+   *
+   * @param \Drupal\Core\Extension\Extension $theme
+   *   The theme extension object.
+   * @param \Drupal\Core\Extension\Extension[] $base_themes
+   *   An array of base themes.
+   *
+   * @return string[]
+   *   The list of stylesheets-remove specified in the *.info.yml file.
+   *
+   * @todo Remove in Drupal 9.0.x.
+   */
+  protected function prepareStylesheetsRemove(Extension $theme, $base_themes) {
+    // Prepare stylesheets from this theme as well as all ancestor themes.
+    // We work it this way so that we can have child themes remove CSS files
+    // easily from parent.
+    $stylesheets_remove = array();
+    // Grab stylesheets from base theme.
+    foreach ($base_themes as $base) {
+      $base_theme_path = $base->getPath();
+      if (!empty($base->info['stylesheets-remove'])) {
+        foreach ($base->info['stylesheets-remove'] as $css_file) {
+          $css_file = $this->resolveStyleSheetPlaceholders($css_file);
+          $stylesheets_remove[$css_file] = $css_file;
+        }
+      }
+    }
+
+    // Add stylesheets used by this theme.
+    if (!empty($theme->info['stylesheets-remove'])) {
+      foreach ($theme->info['stylesheets-remove'] as $css_file) {
+        $css_file = $this->resolveStyleSheetPlaceholders($css_file);
+        $stylesheets_remove[$css_file] = $css_file;
+      }
+    }
+    return $stylesheets_remove;
+  }
+
 }
diff --git a/core/modules/system/src/Tests/Asset/LibraryDiscoveryIntegrationTest.php b/core/modules/system/src/Tests/Asset/LibraryDiscoveryIntegrationTest.php
index 2ddccea..a535ea8 100644
--- a/core/modules/system/src/Tests/Asset/LibraryDiscoveryIntegrationTest.php
+++ b/core/modules/system/src/Tests/Asset/LibraryDiscoveryIntegrationTest.php
@@ -7,39 +7,257 @@
 
 namespace Drupal\system\Tests\Asset;
 
+use Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException;
 use Drupal\simpletest\KernelTestBase;
 
 /**
- * Tests the element info.
+ * Tests the library discovery and library discovery parser.
  *
  * @group Render
  */
 class LibraryDiscoveryIntegrationTest extends KernelTestBase {
 
   /**
+   * The library discovery service.
+   *
+   * @var \Drupal\Core\Asset\LibraryDiscoveryInterface
+   */
+  protected $libraryDiscovery;
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
 
-    $this->container->get('theme_handler')->install(['test_theme', 'classy']);
+    $this->container->get('theme_installer')->install(['test_theme', 'classy']);
+    $this->libraryDiscovery = $this->container->get('library.discovery');
   }
 
   /**
    * Ensures that the element info can be altered by themes.
    */
   public function testElementInfoByTheme() {
+    $this->activateTheme('test_theme');
+    $this->assertTrue($this->libraryDiscovery->getLibraryByName('test_theme', 'kitten'));
+  }
+
+  /**
+   * Tests that libraries-override are applied to library definitions.
+   */
+  public function testLibrariesOverride() {
+    // Assert some classy libraries that will be overridden or removed.
+    $this->activateTheme('classy');
+    $this->assertAssetInLibrary('core/themes/classy/css/components/button.css', 'classy', 'base', 'css');
+    $this->assertAssetInLibrary('core/themes/classy/css/components/collapse-processed.css', 'classy', 'base', 'css');
+    $this->assertAssetInLibrary('core/themes/classy/css/components/container-inline.css', 'classy', 'base', 'css');
+    $this->assertAssetInLibrary('core/themes/classy/css/components/details.css', 'classy', 'base', 'css');
+    $this->assertAssetInLibrary('core/themes/classy/css/components/dialog.css', 'classy', 'dialog', 'css');
+
+    // Confirmatory assert on core library to be removed.
+    $this->assertTrue($this->libraryDiscovery->getLibraryByName('core', 'drupal.progress'), 'Confirmatory test on "core/drupal.progress"');
+
+    // Activate test theme that defines libraries overrides.
+    $this->activateTheme('test_theme');
+
+    // Assert that entire library was correctly overridden.
+    $this->assertEqual($this->libraryDiscovery->getLibraryByName('core', 'drupal.collapse'), $this->libraryDiscovery->getLibraryByName('test_theme', 'collapse'), 'Entire library correctly overridden.');
+
+    // Assert that classy library assets were correctly overridden or removed.
+    $this->assertNoAssetInLibrary('core/themes/classy/css/components/button.css', 'classy', 'base', 'css');
+    $this->assertNoAssetInLibrary('core/themes/classy/css/components/collapse-processed.css', 'classy', 'base', 'css');
+    $this->assertNoAssetInLibrary('core/themes/classy/css/components/container-inline.css', 'classy', 'base', 'css');
+    $this->assertNoAssetInLibrary('core/themes/classy/css/components/details.css', 'classy', 'base', 'css');
+    $this->assertNoAssetInLibrary('core/themes/classy/css/components/dialog.css', 'classy', 'dialog', 'css');
+
+    $this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme/css/my-button.css', 'classy', 'base', 'css');
+    $this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme/css/my-collapse-processed.css', 'classy', 'base', 'css');
+    $this->assertAssetInLibrary('themes/my_theme/css/my-container-inline.css', 'classy', 'base', 'css');
+    $this->assertAssetInLibrary('themes/my_theme/css/my-details.css', 'classy', 'base', 'css');
+
+    // Assert that entire library was correctly removed.
+    $this->assertFalse($this->libraryDiscovery->getLibraryByName('core', 'drupal.progress'), 'Entire library correctly removed.');
+
+    // Assert that overridden library asset still retains attributes.
+    $library = $this->libraryDiscovery->getLibraryByName('core', 'jquery');
+    foreach ($library['js'] as $definition) {
+      if ($definition['data'] == 'core/modules/system/tests/themes/test_theme/js/collapse.js') {
+        $this->assertTrue($definition['minified'] && $definition['weight'] == -20, 'Previous attributes retained');
+        break;
+      }
+    }
+  }
+
+  /**
+   * Tests libraries-override on drupalSettings.
+   */
+  public function testLibrariesOverrideDrupalSettings() {
+    // Activate test theme that attempts to override drupalSettings.
+    $this->activateTheme('test_theme_libraries_override_with_drupal_settings');
+
+    // Assert that drupalSettings cannot be overridden and throws an exception.
+    try {
+      $this->libraryDiscovery->getLibraryByName('core', 'drupal.ajax');
+      $this->fail('Throw Exception when trying to override drupalSettings');
+    }
+    catch (InvalidLibrariesOverrideSpecificationException $e) {
+      $expected_message = 'drupalSettings may not be overridden in libraries-override. Trying to override core/drupal.ajax/drupalSettings. Use hook_library_info_alter() instead.';
+      $this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when trying to override drupalSettings');
+    }
+  }
+
+  /**
+   * Tests libraries-override on malformed assets.
+   */
+  public function testLibrariesOverrideMalformedAsset() {
+    // Activate test theme that overrides with a malformed asset.
+    $this->activateTheme('test_theme_libraries_override_with_invalid_asset');
+
+    // Assert that improperly formed asset "specs" throw an exception.
+    try {
+      $this->libraryDiscovery->getLibraryByName('core', 'drupal.dialog');
+      $this->fail('Throw Exception when specifying invalid override');
+    }
+    catch (InvalidLibrariesOverrideSpecificationException $e) {
+      $expected_message = 'Library asset core/drupal.dialog/css is not correctly specified. It should be in the form "extension/library_name/sub_key/path/to/asset.js".';
+      $this->assertEqual($e->getMessage(), $expected_message, 'Throw Exception when specifying invalid override');
+    }
+  }
+
+  /**
+   * Tests library assets with other ways for specifying paths.
+   */
+  public function testLibrariesOverrideOtherAssetLibraryNames() {
+    // Activate a test theme that defines libraries overrides on other types of
+    // assets.
+    $this->activateTheme('test_theme');
+
+    // Assert Drupal-relative paths.
+    $this->assertAssetInLibrary('themes/my_theme/css/dropbutton.css', 'core', 'drupal.dropbutton', 'css');
+
+    // Assert stream wrapper paths.
+    $this->assertAssetInLibrary('public://my_css/vertical-tabs.css', 'core', 'drupal.vertical-tabs', 'css');
+
+    // Assert a protocol-relative URI.
+    $this->assertAssetInLibrary('//my-server/my_theme/css/jquery_ui.css', 'core', 'jquery.ui', 'css');
+
+    // Assert an absolute URI.
+    $this->assertAssetInLibrary('http://example.com/my_theme/css/farbtastic.css', 'core', 'jquery.farbtastic', 'css');
+  }
+
+  /**
+   * Tests that base theme libraries-override still apply in sub themes.
+   */
+  public function testBaseThemeLibrariesOverrideInSubTheme() {
+    // Activate a test theme that has subthemes.
+    $this->activateTheme('test_subtheme');
+
+    // Assert that libraries-override specified in the base theme still applies
+    // in the sub theme.
+    $this->assertNoAssetInLibrary('core/misc/dialog/dialog.js', 'core', 'drupal.dialog', 'js');
+    $this->assertAssetInLibrary('core/modules/system/tests/themes/test_basetheme/css/farbtastic.css', 'core', 'jquery.farbtastic', 'css');
+  }
+
+  /**
+   * Tests libraries-extend.
+   */
+  public function testLibrariesExtend() {
+    // Activate classy themes and verify the libraries are not extended.
+    $this->activateTheme('classy');
+    $this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_1.css', 'classy', 'book-navigation', 'css');
+    $this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/js/extend_1.js', 'classy', 'book-navigation', 'js');
+    $this->assertNoAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_2.css', 'classy', 'book-navigation', 'css');
+
+    // Activate the theme that extends the book-navigation library in classy.
+    $this->activateTheme('test_theme_libraries_extend');
+    $this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_1.css', 'classy', 'book-navigation', 'css');
+    $this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/js/extend_1.js', 'classy', 'book-navigation', 'js');
+    $this->assertAssetInLibrary('core/modules/system/tests/themes/test_theme_libraries_extend/css/extend_2.css', 'classy', 'book-navigation', 'css');
+  }
+
+  /**
+   * Activates a specified theme.
+   *
+   * Installs the theme if not already installed and makes it the active theme.
+   *
+   * @param string $theme_name
+   *   The name of the theme to be activated.
+   */
+  protected function activateTheme($theme_name) {
+    $this->container->get('theme_installer')->install([$theme_name]);
+
     /** @var \Drupal\Core\Theme\ThemeInitializationInterface $theme_initializer */
     $theme_initializer = $this->container->get('theme.initialization');
 
     /** @var \Drupal\Core\Theme\ThemeManagerInterface $theme_manager */
     $theme_manager = $this->container->get('theme.manager');
 
-    /** @var \Drupal\Core\Render\ElementInfoManagerInterface $element_info */
-    $library_discovery = $this->container->get('library.discovery');
+    $theme_manager->setActiveTheme($theme_initializer->getActiveThemeByName($theme_name));
+
+    $this->libraryDiscovery->clearCachedDefinitions();
+
+    // Assert message.
+    $this->pass(sprintf('Activated theme "%s"', $theme_name));
+  }
 
-    $theme_manager->setActiveTheme($theme_initializer->getActiveThemeByName('test_theme'));
-    $this->assertTrue($library_discovery->getLibraryByName('test_theme', 'kitten'));
+  /**
+   * Asserts that the specified asset is in the given library.
+   *
+   * @param string $asset
+   *   The asset file with the path for the file.
+   * @param string $extension
+   *   The extension in which the $library is defined.
+   * @param string $library_name
+   *   Name of the library.
+   * @param mixed $sub_key
+   *   The library sub key where the given asset is defined.
+   * @param string $message
+   *   (optional) A message to display with the assertion.
+   *
+   * @return bool
+   *   TRUE if the specified asset is found in the library.
+   */
+  protected function assertAssetInLibrary($asset, $extension, $library_name, $sub_key, $message = NULL) {
+    if (!isset($message)) {
+      $message = sprintf('Asset %s found in library "%s/%s"', $asset, $extension, $library_name);
+    }
+    $library = $this->libraryDiscovery->getLibraryByName($extension, $library_name);
+    foreach ($library[$sub_key] as $definition) {
+      if ($asset == $definition['data']) {
+        return $this->pass($message);
+      }
+    }
+    return $this->fail($message);
+  }
+
+  /**
+   * Asserts that the specified asset is not in the given library.
+   *
+   * @param string $asset
+   *   The asset file with the path for the file.
+   * @param string $extension
+   *   The extension in which the $library_name is defined.
+   * @param string $library_name
+   *   Name of the library.
+   * @param mixed $sub_key
+   *   The library sub key where the given asset is defined.
+   * @param string $message
+   *   (optional) A message to display with the assertion.
+   *
+   * @return bool
+   *   TRUE if the specified asset is not found in the library.
+   */
+  protected function assertNoAssetInLibrary($asset, $extension, $library_name, $sub_key, $message = NULL) {
+    if (!isset($message)) {
+      $message = sprintf('Asset %s not found in library "%s/%s"', $asset, $extension, $library_name);
+    }
+    $library = $this->libraryDiscovery->getLibraryByName($extension, $library_name);
+    foreach ($library[$sub_key] as $definition) {
+      if ($asset == $definition['data']) {
+        return $this->fail($message);
+      }
+    }
+    return $this->pass($message);
   }
 
 }
diff --git a/core/modules/system/src/Tests/Theme/ThemeTest.php b/core/modules/system/src/Tests/Theme/ThemeTest.php
index 4aafc4f..0759a97 100644
--- a/core/modules/system/src/Tests/Theme/ThemeTest.php
+++ b/core/modules/system/src/Tests/Theme/ThemeTest.php
@@ -175,7 +175,7 @@ function testCSSOverride() {
     $config->set('css.preprocess', 0);
     $config->save();
     $this->drupalGet('theme-test/suggestion');
-    $this->assertNoText('system.module.css', 'The theme\'s .info.yml file is able to override a module CSS file from being added to the page.');
+    $this->assertNoText('system.module.css', "The theme's .info.yml file is able to remove a module CSS file from being added to the page.");
 
     // Also test with aggregation enabled, simply ensuring no PHP errors are
     // triggered during drupal_build_css_cache() when a source file doesn't
diff --git a/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml b/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml
index dcb1a2f..3637a0c 100644
--- a/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml
+++ b/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml
@@ -7,3 +7,11 @@ libraries:
   - test_basetheme/global-styling
 stylesheets-remove:
   - '@theme_test/css/base-remove.css'
+libraries-override:
+  core/drupal.dialog:
+    js:
+      misc/dialog/dialog.js: false
+  core/jquery.farbtastic:
+    css:
+      component:
+        assets/vendor/farbtastic/farbtastic.css: css/farbtastic.css
diff --git a/core/modules/system/tests/themes/test_theme/css/collapse.css b/core/modules/system/tests/themes/test_theme/css/collapse.css
new file mode 100644
index 0000000..23f38b3
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme/css/collapse.css
@@ -0,0 +1,4 @@
+/**
+ * @file
+ * Test CSS asset file for test_theme.theme.
+ */
diff --git a/core/modules/system/tests/themes/test_theme/js/collapse.js b/core/modules/system/tests/themes/test_theme/js/collapse.js
new file mode 100644
index 0000000..4d66841
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme/js/collapse.js
@@ -0,0 +1,4 @@
+/**
+ * @file
+ * Test JS asset file for test_theme.theme.
+ */
diff --git a/core/modules/system/tests/themes/test_theme/test_theme.info.yml b/core/modules/system/tests/themes/test_theme/test_theme.info.yml
index 8f613bf..4c1568c 100644
--- a/core/modules/system/tests/themes/test_theme/test_theme.info.yml
+++ b/core/modules/system/tests/themes/test_theme/test_theme.info.yml
@@ -18,6 +18,49 @@ stylesheets-remove:
   - '@system/css/system.module.css'
 libraries:
   - test_theme/global-styling
+libraries-override:
+  # Replace an entire library.
+  core/drupal.collapse: test_theme/collapse
+  # Remove an entire library.
+  core/drupal.progress: false
+  # Replace particular library assets.
+  classy/base:
+    css:
+      component:
+        css/components/button.css: css/my-button.css
+        css/components/collapse-processed.css: css/my-collapse-processed.css
+        css/components/container-inline.css: /themes/my_theme/css/my-container-inline.css
+        css/components/details.css: /themes/my_theme/css/my-details.css
+  # Remove particular library assets.
+  classy/dialog:
+    css:
+      component:
+        css/components/dialog.css: false
+  # It works for JS as well.
+  core/jquery:
+    js:
+      assets/vendor/jquery/jquery.min.js: js/collapse.js
+  # Use Drupal-relative paths.
+  core/drupal.dropbutton:
+    css:
+      component:
+        misc/dropbutton/dropbutton.css: /themes/my_theme/css/dropbutton.css
+  # Use stream wrappers.
+  core/drupal.vertical-tabs:
+    css:
+      component:
+        misc/vertical-tabs.css: public://my_css/vertical-tabs.css
+  # Use a protocol-relative URI.
+  core/jquery.ui:
+    css:
+      component:
+        assets/vendor/jquery.ui/themes/base/core.css: //my-server/my_theme/css/jquery_ui.css
+  # Use an absolute URI.
+  core/jquery.farbtastic:
+    css:
+      component:
+        assets/vendor/farbtastic/farbtastic.css: http://example.com/my_theme/css/farbtastic.css
+
 regions:
   content: Content
   left: Left
diff --git a/core/modules/system/tests/themes/test_theme/test_theme.libraries.yml b/core/modules/system/tests/themes/test_theme/test_theme.libraries.yml
index c1fe4a5..52bb147 100644
--- a/core/modules/system/tests/themes/test_theme/test_theme.libraries.yml
+++ b/core/modules/system/tests/themes/test_theme/test_theme.libraries.yml
@@ -3,3 +3,11 @@ global-styling:
   css:
     base:
       kitten.css: {}
+
+collapse:
+  version: VERSION
+  js:
+    js/collapse.js: { }
+  css:
+    base:
+      css/collapse.css: { }
diff --git a/core/modules/system/tests/themes/test_theme_libraries_extend/test_theme_libraries_extend.info.yml b/core/modules/system/tests/themes/test_theme_libraries_extend/test_theme_libraries_extend.info.yml
new file mode 100644
index 0000000..f312c89
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_libraries_extend/test_theme_libraries_extend.info.yml
@@ -0,0 +1,10 @@
+name: 'Test theme libraries-extend'
+type: theme
+description: 'Test Theme with libraries-extend'
+version: VERSION
+base theme: classy
+core: 8.x
+libraries-extend:
+  classy/book-navigation:
+    - test_theme_libraries_extend/extend_one
+    - test_theme_libraries_extend/extend_two
diff --git a/core/modules/system/tests/themes/test_theme_libraries_extend/test_theme_libraries_extend.libraries.yml b/core/modules/system/tests/themes/test_theme_libraries_extend/test_theme_libraries_extend.libraries.yml
new file mode 100644
index 0000000..a276151
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_libraries_extend/test_theme_libraries_extend.libraries.yml
@@ -0,0 +1,11 @@
+extend_one:
+  css:
+    theme:
+      css/extend_1.css: { }
+  js:
+    js/extend_1.js: { }
+
+extend_two:
+  css:
+    theme:
+      css/extend_2.css: { }
diff --git a/core/modules/system/tests/themes/test_theme_libraries_override_with_drupal_settings/test_theme_libraries_override_with_drupal_settings.info.yml b/core/modules/system/tests/themes/test_theme_libraries_override_with_drupal_settings/test_theme_libraries_override_with_drupal_settings.info.yml
new file mode 100644
index 0000000..f55f6d0
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_libraries_override_with_drupal_settings/test_theme_libraries_override_with_drupal_settings.info.yml
@@ -0,0 +1,12 @@
+name: 'Test theme libraries-override'
+type: theme
+description: 'Theme with drupalSettings libraries-override'
+version: VERSION
+base theme: classy
+core: 8.x
+libraries-override:
+  # drupalSettings libraries override. Should throw a
+  # \Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException.
+  core/drupal.ajax:
+    drupalSettings:
+      ajaxPageState: { }
diff --git a/core/modules/system/tests/themes/test_theme_libraries_override_with_invalid_asset/test_theme_libraries_override_with_invalid_asset.info.yml b/core/modules/system/tests/themes/test_theme_libraries_override_with_invalid_asset/test_theme_libraries_override_with_invalid_asset.info.yml
new file mode 100644
index 0000000..f31ade0
--- /dev/null
+++ b/core/modules/system/tests/themes/test_theme_libraries_override_with_invalid_asset/test_theme_libraries_override_with_invalid_asset.info.yml
@@ -0,0 +1,11 @@
+name: 'Test theme libraries-override'
+type: theme
+description: 'Theme with invalid libraries-override asset spec.'
+version: VERSION
+base theme: classy
+core: 8.x
+libraries-override:
+  # A malformed library asset name. Should throw a
+  # \Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException.
+  core/drupal.dialog:
+    css: false
diff --git a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryCollectorTest.php b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryCollectorTest.php
index 1c3733d..6199438 100644
--- a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryCollectorTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryCollectorTest.php
@@ -94,7 +94,7 @@ public function testResolveCacheMiss() {
     $this->activeTheme = $this->getMockBuilder('Drupal\Core\Theme\ActiveTheme')
       ->disableOriginalConstructor()
       ->getMock();
-    $this->themeManager->expects($this->once())
+    $this->themeManager->expects($this->exactly(3))
       ->method('getActiveTheme')
       ->willReturn($this->activeTheme);
     $this->activeTheme->expects($this->once())
@@ -120,7 +120,7 @@ public function testDestruct() {
     $this->activeTheme = $this->getMockBuilder('Drupal\Core\Theme\ActiveTheme')
       ->disableOriginalConstructor()
       ->getMock();
-    $this->themeManager->expects($this->once())
+    $this->themeManager->expects($this->exactly(3))
       ->method('getActiveTheme')
       ->willReturn($this->activeTheme);
     $this->activeTheme->expects($this->once())
diff --git a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
index 9865cb2..2f5ed21 100644
--- a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
@@ -73,6 +73,15 @@ protected function setUp() {
 
     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
     $this->themeManager = $this->getMock('Drupal\Core\Theme\ThemeManagerInterface');
+    $mock_active_theme = $this->getMockBuilder('Drupal\Core\Theme\ActiveTheme')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $mock_active_theme->expects($this->any())
+      ->method('getLibrariesOverride')
+      ->willReturn([]);
+    $this->themeManager->expects($this->any())
+      ->method('getActiveTheme')
+      ->willReturn($mock_active_theme);
     $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager);
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php b/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php
index 0cb5a25..e0c20cd 100644
--- a/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php
+++ b/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php
@@ -93,7 +93,8 @@ public function testGetRegistryForModule() {
       'engine' => 'twig',
       'owner' => 'twig',
       'stylesheets_remove' => [],
-      'stylesheets_override' => [],
+      'libraries_override' => [],
+      'libraries_extend' => [],
       'libraries' => [],
       'extension' => '.twig',
       'base_themes' => [],
diff --git a/core/themes/bartik/bartik.info.yml b/core/themes/bartik/bartik.info.yml
index 4ee4487..a74f90c 100644
--- a/core/themes/bartik/bartik.info.yml
+++ b/core/themes/bartik/bartik.info.yml
@@ -31,4 +31,3 @@ regions:
   footer_third: 'Footer third'
   footer_fourth: 'Footer fourth'
   footer_fifth: 'Footer fifth'
-
diff --git a/core/themes/seven/seven.info.yml b/core/themes/seven/seven.info.yml
index b0911be..b983303 100644
--- a/core/themes/seven/seven.info.yml
+++ b/core/themes/seven/seven.info.yml
@@ -8,8 +8,11 @@ version: VERSION
 core: 8.x
 libraries:
  - seven/global-styling
-stylesheets-remove:
-  - core/assets/vendor/jquery.ui/themes/base/dialog.css
+libraries-override:
+  core/jquery.ui.dialog:
+    css:
+      component:
+        assets/vendor/jquery.ui/themes/base/dialog.css: false
 quickedit_stylesheets:
   - css/components/quickedit.css
 regions:
