diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index b71e437dcbab51af7031f1de04a5793a3877f225..04b41ce4bf4d5311c671f61022c768ee22a8b2f3 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -343,10 +343,10 @@ function theme_get_setting($setting_name, $theme = NULL) {
 
       // Generate the path to the logo image.
       if ($cache[$theme]->get('logo.use_default')) {
-        $cache[$theme]->set('logo.url', file_create_url($theme_object->getPath() . '/logo.svg'));
+        $cache[$theme]->set('logo.url', file_url_transform_relative(file_create_url($theme_object->getPath() . '/logo.svg')));
       }
       elseif ($logo_path = $cache[$theme]->get('logo.path')) {
-        $cache[$theme]->set('logo.url', file_create_url($logo_path));
+        $cache[$theme]->set('logo.url', file_url_transform_relative(file_create_url($logo_path)));
       }
 
       // Generate the path to the favicon.
@@ -354,14 +354,14 @@ function theme_get_setting($setting_name, $theme = NULL) {
         $favicon_path = $cache[$theme]->get('favicon.path');
         if ($cache[$theme]->get('favicon.use_default')) {
           if (file_exists($favicon = $theme_object->getPath() . '/favicon.ico')) {
-            $cache[$theme]->set('favicon.url', file_create_url($favicon));
+            $cache[$theme]->set('favicon.url', file_url_transform_relative(file_create_url($favicon)));
           }
           else {
-            $cache[$theme]->set('favicon.url', file_create_url('core/misc/favicon.ico'));
+            $cache[$theme]->set('favicon.url', file_url_transform_relative(file_create_url('core/misc/favicon.ico')));
           }
         }
         elseif ($favicon_path) {
-          $cache[$theme]->set('favicon.url', file_create_url($favicon_path));
+          $cache[$theme]->set('favicon.url', file_url_transform_relative(file_create_url($favicon_path)));
         }
         else {
           $cache[$theme]->set('features.favicon', FALSE);
@@ -756,7 +756,7 @@ function template_preprocess_links(&$variables) {
  */
 function template_preprocess_image(&$variables) {
   if (!empty($variables['uri'])) {
-    $variables['attributes']['src'] = file_create_url($variables['uri']);
+    $variables['attributes']['src'] = file_url_transform_relative(file_create_url($variables['uri']));
   }
   // Generate a srcset attribute conforming to the spec at
   // http://www.w3.org/html/wg/drafts/html/master/embedded-content.html#attr-img-srcset
@@ -764,7 +764,7 @@ function template_preprocess_image(&$variables) {
     $srcset = array();
     foreach ($variables['srcset'] as $src) {
       // URI is mandatory.
-      $source = file_create_url($src['uri']);
+      $source = file_url_transform_relative(file_create_url($src['uri']));
       if (isset($src['width']) && !empty($src['width'])) {
         $source .= ' ' . $src['width'];
       }
diff --git a/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php b/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
index 49e4675e1b7d83e55a3111d168ac6056990d76b5..0f70dbf593eaba961c36d2d3ceb4000efb6786ae 100644
--- a/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
+++ b/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
@@ -135,7 +135,7 @@ public function render(array $css_assets) {
           // assets: output a LINK tag for a file CSS asset.
           if (count($css_assets) <= 31) {
             $element = $link_element_defaults;
-            $element['#attributes']['href'] = file_create_url($css_asset['data']) . $query_string_separator . $query_string;
+            $element['#attributes']['href'] = file_url_transform_relative(file_create_url($css_asset['data'])) . $query_string_separator . $query_string;
             $element['#attributes']['media'] = $css_asset['media'];
             $element['#browsers'] = $css_asset['browsers'];
             $elements[] = $element;
@@ -148,7 +148,7 @@ public function render(array $css_assets) {
             // LINK tag.
             if (!$css_asset['preprocess']) {
               $element = $link_element_defaults;
-              $element['#attributes']['href'] = file_create_url($css_asset['data']) . $query_string_separator . $query_string;
+              $element['#attributes']['href'] = file_url_transform_relative(file_create_url($css_asset['data'])) . $query_string_separator . $query_string;
               $element['#attributes']['media'] = $css_asset['media'];
               $element['#browsers'] = $css_asset['browsers'];
               $elements[] = $element;
@@ -168,7 +168,7 @@ public function render(array $css_assets) {
                 // control browser-caching. IE7 does not support a media type on
                 // the @import statement, so we instead specify the media for
                 // the group on the STYLE tag.
-                $import[] = '@import url("' . Html::escape(file_create_url($next_css_asset['data']) . '?' . $query_string) . '");';
+                $import[] = '@import url("' . Html::escape(file_url_transform_relative(file_create_url($next_css_asset['data'])) . '?' . $query_string) . '");';
                 // Move the outer for loop skip the next item, since we
                 // processed it here.
                 $i = $j;
diff --git a/core/lib/Drupal/Core/Asset/CssOptimizer.php b/core/lib/Drupal/Core/Asset/CssOptimizer.php
index dc34a237abdf008b588d1ca3298bc7eec539b1f2..704ee571e4e87fe5c0961d912dc9125c1fc8ab42 100644
--- a/core/lib/Drupal/Core/Asset/CssOptimizer.php
+++ b/core/lib/Drupal/Core/Asset/CssOptimizer.php
@@ -265,7 +265,7 @@ public function rewriteFileURI($matches) {
       $last = $path;
       $path = preg_replace('`(^|/)(?!\.\./)([^/]+)/\.\./`', '$1', $path);
     }
-    return 'url(' . file_create_url($path) . ')';
+    return 'url(' . file_url_transform_relative(file_create_url($path)) . ')';
   }
 
 }
diff --git a/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php b/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php
index 70832e9d9d1027b5240043666fed1bde39e58ad0..b0d22f15cf94ca4f95937934da7bd289b35b084e 100644
--- a/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php
+++ b/core/lib/Drupal/Core/Asset/JsCollectionRenderer.php
@@ -79,7 +79,7 @@ public function render(array $js_assets) {
         case 'file':
           $query_string = $js_asset['version'] == -1 ? $default_query_string : 'v=' . $js_asset['version'];
           $query_string_separator = (strpos($js_asset['data'], '?') !== FALSE) ? '&' : '?';
-          $element['#attributes']['src'] = file_create_url($js_asset['data']);
+          $element['#attributes']['src'] = file_url_transform_relative(file_create_url($js_asset['data']));
           // Only add the cache-busting query string if this isn't an aggregate
           // file.
           if (!isset($js_asset['preprocessed'])) {
diff --git a/core/lib/Drupal/Core/Render/Element/ImageButton.php b/core/lib/Drupal/Core/Render/Element/ImageButton.php
index 4ee39a6340f32bb96a737238b7e5c21e6aa79119..f22ae1decf8cd221dfaeb82aa108e64c8f71096a 100644
--- a/core/lib/Drupal/Core/Render/Element/ImageButton.php
+++ b/core/lib/Drupal/Core/Render/Element/ImageButton.php
@@ -75,7 +75,7 @@ public static function preRenderButton($element) {
     $element['#attributes']['type'] = 'image';
     Element::setAttributes($element, array('id', 'name', 'value'));
 
-    $element['#attributes']['src'] = file_create_url($element['#src']);
+    $element['#attributes']['src'] = file_url_transform_relative(file_create_url($element['#src']));
     if (!empty($element['#title'])) {
       $element['#attributes']['alt'] = $element['#title'];
       $element['#attributes']['title'] = $element['#title'];
diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index 5b71c5290bdc10e1c267ddfe1ce7547a13b2b53c..73b2ca9c6554167d4bc8ba225e78b9b2208ccc29 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -135,7 +135,9 @@ public function getFunctions() {
       new \Twig_SimpleFunction('url', array($this, 'getUrl'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))),
       new \Twig_SimpleFunction('path', array($this, 'getPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))),
       new \Twig_SimpleFunction('link', array($this, 'getLink')),
-      new \Twig_SimpleFunction('file_url', 'file_create_url'),
+      new \Twig_SimpleFunction('file_url', function ($uri) {
+        return file_url_transform_relative(file_create_url($uri));
+      }),
       new \Twig_SimpleFunction('attach_library', [$this, 'attachLibrary']),
       new \Twig_SimpleFunction('active_theme_path', [$this, 'getActiveThemePath']),
       new \Twig_SimpleFunction('active_theme', [$this, 'getActiveTheme']),
diff --git a/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php b/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php
index 5ae5e85b21059bb4200766e41c7a4a535c86da5f..8072060697003963ee23c6ec8f6c3117108ac7f7 100644
--- a/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php
+++ b/core/modules/ckeditor/src/Plugin/Editor/CKEditor.php
@@ -298,8 +298,11 @@ public function getJSSettings(EditorEntity $editor) {
     );
 
     // Finally, set Drupal-specific CKEditor settings.
+    $root_relative_file_url = function ($uri) {
+      return file_url_transform_relative(file_create_url($uri));
+    };
     $settings += array(
-      'drupalExternalPlugins' => array_map('file_create_url', $external_plugin_files),
+      'drupalExternalPlugins' => array_map($root_relative_file_url, $external_plugin_files),
     );
 
     // Parse all CKEditor plugin JavaScript files for translations.
@@ -421,6 +424,7 @@ public function buildContentsCssJSSetting(EditorEntity $editor) {
     $this->moduleHandler->alter('ckeditor_css', $css, $editor);
     $css = array_merge($css, _ckeditor_theme_css());
     $css = array_map('file_create_url', $css);
+    $css = array_map('file_url_transform_relative', $css);
 
     return array_values($css);
   }
diff --git a/core/modules/ckeditor/src/Tests/CKEditorTest.php b/core/modules/ckeditor/src/Tests/CKEditorTest.php
index 4df0113333105b45792ab1d3748519aa96848676..6a2fd426495ddff320ec23a08e44ec429d1ff0cf 100644
--- a/core/modules/ckeditor/src/Tests/CKEditorTest.php
+++ b/core/modules/ckeditor/src/Tests/CKEditorTest.php
@@ -90,8 +90,8 @@ function testGetJSSettings() {
       'language' => 'en',
       'stylesSet' => FALSE,
       'drupalExternalPlugins' => array(
-        'drupalimage' => file_create_url('core/modules/ckeditor/js/plugins/drupalimage/plugin.js'),
-        'drupallink' => file_create_url('core/modules/ckeditor/js/plugins/drupallink/plugin.js'),
+        'drupalimage' => file_url_transform_relative(file_create_url('core/modules/ckeditor/js/plugins/drupalimage/plugin.js')),
+        'drupallink' => file_url_transform_relative(file_create_url('core/modules/ckeditor/js/plugins/drupallink/plugin.js')),
       ),
     );
     $expected_config = $this->castSafeStrings($expected_config);
@@ -114,9 +114,9 @@ function testGetJSSettings() {
     $expected_config['toolbar'][0]['items'][] = 'Format';
     $expected_config['format_tags'] = 'p;h2;h3;h4;h5;h6';
     $expected_config['extraPlugins'] .= ',llama_contextual,llama_contextual_and_button';
-    $expected_config['drupalExternalPlugins']['llama_contextual'] = file_create_url('core/modules/ckeditor/tests/modules/js/llama_contextual.js');
-    $expected_config['drupalExternalPlugins']['llama_contextual_and_button'] = file_create_url('core/modules/ckeditor/tests/modules/js/llama_contextual_and_button.js');
-    $expected_config['contentsCss'][] = file_create_url('core/modules/ckeditor/tests/modules/ckeditor_test.css');
+    $expected_config['drupalExternalPlugins']['llama_contextual'] = file_url_transform_relative(file_create_url('core/modules/ckeditor/tests/modules/js/llama_contextual.js'));
+    $expected_config['drupalExternalPlugins']['llama_contextual_and_button'] = file_url_transform_relative(file_create_url('core/modules/ckeditor/tests/modules/js/llama_contextual_and_button.js'));
+    $expected_config['contentsCss'][] = file_url_transform_relative(file_create_url('core/modules/ckeditor/tests/modules/ckeditor_test.css'));
     ksort($expected_config);
     $this->assertIdentical($expected_config, $this->castSafeStrings($this->ckeditor->getJSSettings($editor)), 'Generated JS settings are correct for customized configuration.');
 
@@ -261,16 +261,16 @@ function testBuildContentsCssJSSetting() {
 
     // Enable the editor_test module, which implements hook_ckeditor_css_alter().
     $this->enableModules(array('ckeditor_test'));
-    $expected[] = file_create_url('core/modules/ckeditor/tests/modules/ckeditor_test.css');
+    $expected[] = file_url_transform_relative(file_create_url('core/modules/ckeditor/tests/modules/ckeditor_test.css'));
     $this->assertIdentical($expected, $this->ckeditor->buildContentsCssJSSetting($editor), '"contentsCss" configuration part of JS settings built correctly while a hook_ckeditor_css_alter() implementation exists.');
 
     // Enable the Bartik theme, which specifies a CKEditor stylesheet.
     \Drupal::service('theme_handler')->install(['bartik']);
     \Drupal::service('theme_handler')->setDefault('bartik');
-    $expected[] = file_create_url('core/themes/bartik/css/base/elements.css');
-    $expected[] = file_create_url('core/themes/bartik/css/components/captions.css');
-    $expected[] = file_create_url('core/themes/bartik/css/components/table.css');
-    $expected[] = file_create_url('core/themes/bartik/css/components/text-formatted.css');
+    $expected[] = file_url_transform_relative(file_create_url('core/themes/bartik/css/base/elements.css'));
+    $expected[] = file_url_transform_relative(file_create_url('core/themes/bartik/css/components/captions.css'));
+    $expected[] = file_url_transform_relative(file_create_url('core/themes/bartik/css/components/table.css'));
+    $expected[] = file_url_transform_relative(file_create_url('core/themes/bartik/css/components/text-formatted.css'));
     $this->assertIdentical($expected, $this->ckeditor->buildContentsCssJSSetting($editor), '"contentsCss" configuration part of JS settings built correctly while a theme providing a CKEditor stylesheet exists.');
   }
 
@@ -479,8 +479,8 @@ protected function getDefaultToolbarConfig() {
 
   protected function getDefaultContentsCssConfig() {
     return array(
-      file_create_url('core/modules/ckeditor/css/ckeditor-iframe.css'),
-      file_create_url('core/modules/system/css/components/align.module.css'),
+      file_url_transform_relative(file_create_url('core/modules/ckeditor/css/ckeditor-iframe.css')),
+      file_url_transform_relative(file_create_url('core/modules/system/css/components/align.module.css')),
     );
   }
 
diff --git a/core/modules/ckeditor/src/Tests/CKEditorToolbarButtonTest.php b/core/modules/ckeditor/src/Tests/CKEditorToolbarButtonTest.php
index 5751f8629ad70792351b2ee569b35188b5d898fd..4b241d7997b1f856cba5b61c8ba06c96213029e7 100644
--- a/core/modules/ckeditor/src/Tests/CKEditorToolbarButtonTest.php
+++ b/core/modules/ckeditor/src/Tests/CKEditorToolbarButtonTest.php
@@ -57,7 +57,6 @@ protected function setUp() {
    * Method tests CKEditor image buttons.
    */
   public function testImageButtonDisplay() {
-    global $base_url;
     $this->drupalLogin($this->admin_user);
 
     // Install the Arabic language (which is RTL) and configure as the default.
@@ -75,7 +74,7 @@ public function testImageButtonDisplay() {
     $json_encode = function($html) {
       return trim(Json::encode($html), '"');
     };
-    $markup = $json_encode($base_url . '/core/modules/ckeditor/js/plugins/drupalimage/image.png');
+    $markup = $json_encode(file_url_transform_relative(file_create_url('core/modules/ckeditor/js/plugins/drupalimage/image.png')));
     $this->assertRaw($markup);
   }
 
diff --git a/core/modules/color/color.module b/core/modules/color/color.module
index 2fbef3034083babad17687e56bd464f39262a00a..055d750f7ddf4dced928b558ed8493ca8b4fa1ca 100644
--- a/core/modules/color/color.module
+++ b/core/modules/color/color.module
@@ -126,7 +126,7 @@ function color_block_view_pre_render(array $build) {
   // Override logo.
   $logo = $config->get('logo');
   if ($logo && $build['content']['site_logo'] && preg_match('!' . $theme_key . '/logo.svg$!', $build['content']['site_logo']['#uri'])) {
-    $build['content']['site_logo']['#uri'] = file_create_url($logo);
+    $build['content']['site_logo']['#uri'] = file_url_transform_relative(file_create_url($logo));
   }
 
   return $build;
diff --git a/core/modules/color/src/Tests/ColorTest.php b/core/modules/color/src/Tests/ColorTest.php
index 4a410644477009ea457a7a45825ba8b3a2af40d6..8e3d7714abe8f894ea3664f59bb998098f10ab26 100644
--- a/core/modules/color/src/Tests/ColorTest.php
+++ b/core/modules/color/src/Tests/ColorTest.php
@@ -121,7 +121,7 @@ function _testColor($theme, $test_values) {
     $this->drupalGet('<front>');
     $stylesheets = $this->config('color.theme.' . $theme)->get('stylesheets');
     foreach ($stylesheets as $stylesheet) {
-      $this->assertPattern('|' . file_create_url($stylesheet) . '|', 'Make sure the color stylesheet is included in the content. (' . $theme . ')');
+      $this->assertPattern('|' . file_url_transform_relative(file_create_url($stylesheet)) . '|', 'Make sure the color stylesheet is included in the content. (' . $theme . ')');
       $stylesheet_content = join("\n", file($stylesheet));
       $this->assertTrue(strpos($stylesheet_content, 'color: #123456') !== FALSE, 'Make sure the color we changed is in the color stylesheet. (' . $theme . ')');
     }
@@ -191,7 +191,7 @@ function testLogoSettingOverride() {
 
     // Ensure that the overridden logo is present in Bartik, which is colorable.
     $this->drupalGet('admin/appearance/settings/bartik');
-    $this->assertIdentical($GLOBALS['base_url'] . '/' . 'core/misc/druplicon.png', $this->getDrupalSettings()['color']['logo']);
+    $this->assertIdentical($GLOBALS['base_path'] . 'core/misc/druplicon.png', $this->getDrupalSettings()['color']['logo']);
   }
 
   /**
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index 08e94384bc70d12e03f2ea0e571d4e4b4cafb3ba..984773ace17c91673d5bd84c0c145f42efa0789e 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -977,7 +977,12 @@ function file_tokens($type, $tokens, array $data, array $options, BubbleableMeta
           break;
 
         case 'url':
+          // Ideally, this would use file_url_transform_relative(), but because
+          // tokens are also often used in e-mails, it's better to keep absolute
+          // file URLs. The 'url.site' cache context is associated to ensure the
+          // correct absolute URL is used in case of a multisite setup.
           $replacements[$original] = file_create_url($file->getFileUri());
+          $bubbleable_metadata->addCacheContexts(['url.site']);
           break;
 
         // These tokens are default variations on the chained tokens handled below.
@@ -1228,7 +1233,13 @@ function template_preprocess_file_link(&$variables) {
   $options = array();
 
   $file_entity = ($file instanceof File) ? $file : File::load($file->fid);
+  // @todo Wrap in file_url_transform_relative(). This is currently
+  // impossible. As a work-around, we currently add the 'url.site' cache context
+  // to ensure different file URLs are generated for different sites in a
+  // multisite setup, including HTTP and HTTPS versions of the same site.
+  // Fix in https://www.drupal.org/node/2646744.
   $url = file_create_url($file_entity->getFileUri());
+  $variables['#cache']['contexts'][] = 'url.site';
 
   $mime_type = $file->getMimeType();
   // Set options as per anchor format described at
diff --git a/core/modules/file/src/Entity/File.php b/core/modules/file/src/Entity/File.php
index ae5ca764b2183cc8cd891df3f753bf13c4a87a38..6417488e52b24a70b21737e24d583faeeb23cc9e 100644
--- a/core/modules/file/src/Entity/File.php
+++ b/core/modules/file/src/Entity/File.php
@@ -70,6 +70,8 @@ public function setFileUri($uri) {
 
   /**
    * {@inheritdoc}
+   *
+   * @see file_url_transform_relative()
    */
   public function url($rel = 'canonical', $options = array()) {
     return file_create_url($this->getFileUri());
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php b/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
index fbe14f09ba95c50af42e6891958856de75e55aed..798babd73c13fcfc5aeb0e19731b8bbea44d1260 100644
--- a/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
@@ -52,6 +52,8 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
     $url = NULL;
     // Add support to link to the entity itself.
     if ($this->getSetting('link_to_file')) {
+      // @todo Wrap in file_url_transform_relative(). This is currently
+      // impossible. See below.
       $url = file_create_url($items->getEntity()->uri->value);
     }
 
@@ -63,6 +65,16 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
           '#type' => 'link',
           '#title' => $view_value,
           '#url' => Url::fromUri($url),
+          // @todo Remove the 'url.site' cache context by using a relative file
+          // URL (file_url_transform_relative()). This is currently impossible
+          // because #type => link requires a Url object, and Url objects do not
+          // support relative URLs: they require fully qualified URLs. Fix in
+          // https://www.drupal.org/node/2646744.
+          '#cache' => [
+            'contexts' => [
+              'url.site',
+            ],
+          ],
         ];
       }
       else {
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/FileUriFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/FileUriFormatter.php
index 0a2a855bcdfab5f4343080111cd19d408466d22c..c86cc8e0d99061f6e0c26047df90c4092ab49348 100644
--- a/core/modules/file/src/Plugin/Field/FieldFormatter/FileUriFormatter.php
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileUriFormatter.php
@@ -55,6 +55,9 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
   protected function viewValue(FieldItemInterface $item) {
     $value = $item->value;
     if ($this->getSetting('file_download_path')) {
+      // @todo Wrap in file_url_transform_relative(). This is currently
+      // impossible. See BaseFieldFileFormatterBase::viewElements(). Fix in
+      // https://www.drupal.org/node/2646744.
       $value = file_create_url($value);
     }
     return $value;
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/RSSEnclosureFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/RSSEnclosureFormatter.php
index ab479f32f3c61ad07e85d09f359479f40959af44..2f0a65f67be2506f7827a2422750ba56ae358921 100644
--- a/core/modules/file/src/Plugin/Field/FieldFormatter/RSSEnclosureFormatter.php
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/RSSEnclosureFormatter.php
@@ -33,6 +33,9 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
       $entity->rss_elements[] = array(
         'key' => 'enclosure',
         'attributes' => array(
+          // In RSS feeds, it is necessary to use absolute URLs. The 'url.site'
+          // cache context is already associated with RSS feed responses, so it
+          // does not need to be specified here.
           'url' => file_create_url($file->getFileUri()),
           'length' => $file->getSize(),
           'type' => $file->getMimeType(),
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/UrlPlainFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/UrlPlainFormatter.php
index 6f2264e91d792d53fdbf3ac14bf179953df642b8..0795be2002ce0e4e66ef754e71d794b68123f25f 100644
--- a/core/modules/file/src/Plugin/Field/FieldFormatter/UrlPlainFormatter.php
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/UrlPlainFormatter.php
@@ -30,7 +30,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
 
     foreach ($this->getEntitiesToView($items, $langcode) as $delta => $file) {
       $elements[$delta] = array(
-        '#markup' => file_create_url($file->getFileUri()),
+        '#markup' => file_url_transform_relative(file_create_url($file->getFileUri())),
         '#cache' => array(
           'tags' => $file->getCacheTags(),
         ),
diff --git a/core/modules/file/src/Plugin/views/field/File.php b/core/modules/file/src/Plugin/views/field/File.php
index 615aa9f8e98c2cac0cd59553573ac5833c9ca8bb..0b9c6965ddc1e3da9bbceec71bf49e58cc516144 100644
--- a/core/modules/file/src/Plugin/views/field/File.php
+++ b/core/modules/file/src/Plugin/views/field/File.php
@@ -69,6 +69,12 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
   protected function renderLink($data, ResultRow $values) {
     if (!empty($this->options['link_to_file']) && $data !== NULL && $data !== '') {
       $this->options['alter']['make_link'] = TRUE;
+      // @todo Wrap in file_url_transform_relative(). This is currently
+      // impossible. As a work-around, we could add the 'url.site' cache context
+      // to ensure different file URLs are generated for different sites in a
+      // multisite setup, including HTTP and HTTPS versions of the same site.
+      // But unfortunately it's impossible to bubble a cache context here.
+      // Fix in https://www.drupal.org/node/2646744.
       $this->options['alter']['path'] = file_create_url($this->getValue($values, 'uri'));
     }
 
diff --git a/core/modules/file/src/Tests/FileTokenReplaceTest.php b/core/modules/file/src/Tests/FileTokenReplaceTest.php
index 93a6c67a87dc8a4abdc432721bb160e442ca7012..bfc85de3d4919d4c3141cc41f09dfe55b3de5620 100644
--- a/core/modules/file/src/Tests/FileTokenReplaceTest.php
+++ b/core/modules/file/src/Tests/FileTokenReplaceTest.php
@@ -66,7 +66,8 @@ function testFileTokenReplacement() {
     $metadata_tests['[file:path]'] = $base_bubbleable_metadata;
     $metadata_tests['[file:mime]'] = $base_bubbleable_metadata;
     $metadata_tests['[file:size]'] = $base_bubbleable_metadata;
-    $metadata_tests['[file:url]'] = $base_bubbleable_metadata;
+    $bubbleable_metadata = clone $base_bubbleable_metadata;
+    $metadata_tests['[file:url]'] = $bubbleable_metadata->addCacheContexts(['url.site']);
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $metadata_tests['[file:created]'] = $bubbleable_metadata->addCacheTags(['rendered']);
     $metadata_tests['[file:created:short]'] = $bubbleable_metadata;
diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc
index b3d4a6e7df2b7b0a34c2d4b6dd2539906a49ffa7..777e43855a4124e29ed5ca0bf866c14e61470618 100644
--- a/core/modules/image/image.admin.inc
+++ b/core/modules/image/image.admin.inc
@@ -34,7 +34,7 @@ function template_preprocess_image_style_preview(&$variables) {
   $original_path = \Drupal::config('image.settings')->get('preview_image');
   $original_image = $image_factory->get($original_path);
   $variables['original'] = array(
-    'url' => file_create_url($original_path),
+    'url' => file_url_transform_relative(file_create_url($original_path)),
     'width' => $original_image->getWidth(),
     'height' => $original_image->getHeight(),
   );
@@ -55,7 +55,7 @@ function template_preprocess_image_style_preview(&$variables) {
   }
   $preview_image = $image_factory->get($preview_file);
   $variables['derivative'] = array(
-    'url' => file_create_url($preview_file),
+    'url' => file_url_transform_relative(file_create_url($preview_file)),
     'width' => $preview_image->getWidth(),
     'height' => $preview_image->getHeight(),
   );
diff --git a/core/modules/image/src/ImageStyleInterface.php b/core/modules/image/src/ImageStyleInterface.php
index 95072915148cdb3ba4d3aaeeb20188f366630a0a..e1cad03bbba6f683300934d0405b4a1608cd1794 100644
--- a/core/modules/image/src/ImageStyleInterface.php
+++ b/core/modules/image/src/ImageStyleInterface.php
@@ -70,6 +70,7 @@ public function buildUri($uri);
    *   in an <img> tag. Requesting the URL will cause the image to be created.
    *
    * @see \Drupal\image\Controller\ImageStyleDownloadController::deliver()
+   * @see file_url_transform_relative()
    */
   public function buildUrl($path, $clean_urls = NULL);
 
diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
index 57204152732ca43db034286af8b836fa8849b9b5..55b613a8ff50101fde1d6643fec42daece2f7a63 100644
--- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
@@ -199,9 +199,16 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
     }
 
     foreach ($files as $delta => $file) {
+      $cache_contexts = array();
       if (isset($link_file)) {
         $image_uri = $file->getFileUri();
+        // @todo Wrap in file_url_transform_relative(). This is currently
+        // impossible. As a work-around, we currently add the 'url.site' cache
+        // context to ensure different file URLs are generated for different
+        // sites in a multisite setup, including HTTP and HTTPS versions of the
+        // same site. Fix in https://www.drupal.org/node/2646744.
         $url = Url::fromUri(file_create_url($image_uri));
+        $cache_contexts[] = 'url.site';
       }
       $cache_tags = Cache::mergeTags($cache_tags, $file->getCacheTags());
 
@@ -219,6 +226,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
         '#url' => $url,
         '#cache' => array(
           'tags' => $cache_tags,
+          'contexts' => $cache_contexts,
         ),
       );
     }
diff --git a/core/modules/image/src/Tests/ImageAdminStylesTest.php b/core/modules/image/src/Tests/ImageAdminStylesTest.php
index 08f0adf9abf744270c45a9c474206ebcf1cb59b5..fb59a4809a0755a8103e5508124598af01becbef 100644
--- a/core/modules/image/src/Tests/ImageAdminStylesTest.php
+++ b/core/modules/image/src/Tests/ImageAdminStylesTest.php
@@ -307,7 +307,7 @@ function testStyleReplacement() {
 
     // Test that image is displayed using newly created style.
     $this->drupalGet('node/' . $nid);
-    $this->assertRaw($style->buildUrl($original_uri), format_string('Image displayed using style @style.', array('@style' => $style_name)));
+    $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', array('@style' => $style_name)));
 
     // Rename the style and make sure the image field is updated.
     $new_style_name = strtolower($this->randomMachineName(10));
@@ -322,7 +322,7 @@ function testStyleReplacement() {
 
     // Reload the image style using the new name.
     $style = ImageStyle::load($new_style_name);
-    $this->assertRaw($style->buildUrl($original_uri), 'Image displayed using style replacement style.');
+    $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), 'Image displayed using style replacement style.');
 
     // Delete the style and choose a replacement style.
     $edit = array(
@@ -334,7 +334,7 @@ function testStyleReplacement() {
 
     $replacement_style = ImageStyle::load('thumbnail');
     $this->drupalGet('node/' . $nid);
-    $this->assertRaw($replacement_style->buildUrl($original_uri), 'Image displayed using style replacement style.');
+    $this->assertRaw(file_url_transform_relative($replacement_style->buildUrl($original_uri)), 'Image displayed using style replacement style.');
   }
 
   /**
@@ -441,7 +441,7 @@ function testConfigImport() {
 
     // Test that image is displayed using newly created style.
     $this->drupalGet('node/' . $nid);
-    $this->assertRaw($style->buildUrl($original_uri), format_string('Image displayed using style @style.', array('@style' => $style_name)));
+    $this->assertRaw(file_url_transform_relative($style->buildUrl($original_uri)), format_string('Image displayed using style @style.', array('@style' => $style_name)));
 
     // Copy config to sync, and delete the image style.
     $sync = $this->container->get('config.storage.sync');
diff --git a/core/modules/image/src/Tests/ImageDimensionsTest.php b/core/modules/image/src/Tests/ImageDimensionsTest.php
index 683756a089b3fb9def323430377a26d3c8997224..f232d71197e48201fc701d2ffbf43cc271373507 100644
--- a/core/modules/image/src/Tests/ImageDimensionsTest.php
+++ b/core/modules/image/src/Tests/ImageDimensionsTest.php
@@ -41,7 +41,7 @@ function testImageDimensions() {
     $style = ImageStyle::create(array('name' => 'test', 'label' => 'Test'));
     $style->save();
     $generated_uri = 'public://styles/test/public/'. \Drupal::service('file_system')->basename($original_uri);
-    $url = $style->buildUrl($original_uri);
+    $url = file_url_transform_relative($style->buildUrl($original_uri));
 
     $variables = array(
       '#theme' => 'image_style',
@@ -70,7 +70,7 @@ function testImageDimensions() {
     $style->save();
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" width="120" height="60" alt="" class="image-style-test" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
@@ -91,7 +91,7 @@ function testImageDimensions() {
     $style->save();
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" width="60" height="120" alt="" class="image-style-test" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
@@ -113,7 +113,7 @@ function testImageDimensions() {
     $style->save();
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" width="45" height="90" alt="" class="image-style-test" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
@@ -135,7 +135,7 @@ function testImageDimensions() {
     $style->save();
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" width="45" height="90" alt="" class="image-style-test" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
@@ -153,7 +153,7 @@ function testImageDimensions() {
     $style->save();
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" width="45" height="90" alt="" class="image-style-test" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
@@ -174,7 +174,7 @@ function testImageDimensions() {
     $style->save();
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" alt="" class="image-style-test" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
 
@@ -194,7 +194,7 @@ function testImageDimensions() {
     $style->save();
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" width="30" height="30" alt="" class="image-style-test" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
@@ -215,7 +215,7 @@ function testImageDimensions() {
     $style->save();
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" width="41" height="41" alt="" class="image-style-test" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
@@ -254,10 +254,10 @@ function testImageDimensions() {
     ];
     // PNG original image. Should be resized to 100x100.
     $generated_uri = 'public://styles/test_uri/public/'. \Drupal::service('file_system')->basename($original_uri);
-    $url = $style->buildUrl($original_uri);
+    $url = file_url_transform_relative($style->buildUrl($original_uri));
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" width="100" height="100" alt="" class="image-style-test-uri" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
@@ -267,11 +267,11 @@ function testImageDimensions() {
     $file = $files[1];
     $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME);
     $generated_uri = 'public://styles/test_uri/public/'. \Drupal::service('file_system')->basename($original_uri);
-    $url = $style->buildUrl($original_uri);
+    $url = file_url_transform_relative($style->buildUrl($original_uri));
     $variables['#uri'] = $original_uri;
     $this->assertEqual($this->getImageTag($variables), '<img src="' . $url . '" width="50" height="50" alt="" class="image-style-test-uri" />');
     $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.');
-    $this->drupalGet($url);
+    $this->drupalGet($this->getAbsoluteUrl($url));
     $this->assertResponse(200, 'Image was generated at the URL.');
     $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.');
     $image_file = $image_factory->get($generated_uri);
diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
index 53ba09f076e59a9c1488586381bacfa47a6cc9f3..2ae0fa45fd185d27642002d68d376cd4da1450fe 100644
--- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
@@ -127,6 +127,8 @@ function _testImageFieldFormatters($scheme) {
     $default_output = '<a href="' . file_create_url($image_uri) . '">' . $renderer->renderRoot($image) . '</a>';
     $this->drupalGet('node/' . $nid);
     $this->assertCacheTag($file->getCacheTags()[0]);
+    // @todo Remove in https://www.drupal.org/node/2646744.
+    $this->assertCacheContext('url.site');
     $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
     $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.');
     $this->assertRaw($default_output, 'Image linked to file formatter displaying correctly on full node view.');
@@ -165,7 +167,7 @@ function _testImageFieldFormatters($scheme) {
       '//a[@href=:path]/img[@src=:url and @alt=:alt and @width=:width and @height=:height]',
       array(
         ':path' => $node->url(),
-        ':url' => file_create_url($image['#uri']),
+        ':url' => file_url_transform_relative(file_create_url($image['#uri'])),
         ':width' => $image['#width'],
         ':height' => $image['#height'],
         ':alt' => $alt,
@@ -256,7 +258,7 @@ function testImageFieldSettings() {
     $node = $node_storage->load($nid);
     $file = $node->{$field_name}->entity;
 
-    $url = file_create_url(ImageStyle::load('medium')->buildUrl($file->getFileUri()));
+    $url = file_url_transform_relative(file_create_url(ImageStyle::load('medium')->buildUrl($file->getFileUri())));
     $this->assertTrue($this->cssSelect('img[width=40][height=20][class=image-style-medium][src="' . $url . '"]'));
 
     // Add alt/title fields to the image and verify that they are displayed.
diff --git a/core/modules/image/src/Tests/ImageThemeFunctionTest.php b/core/modules/image/src/Tests/ImageThemeFunctionTest.php
index 060a8afb26c298fb8a6eb848bdf4d25da405440b..44f649ef679f732e83ea4bdee90a1a6bd75dba05 100644
--- a/core/modules/image/src/Tests/ImageThemeFunctionTest.php
+++ b/core/modules/image/src/Tests/ImageThemeFunctionTest.php
@@ -75,7 +75,7 @@ function testImageFormatterTheme() {
     // Create a style.
     $style = ImageStyle::create(array('name' => 'test', 'label' => 'Test'));
     $style->save();
-    $url = $style->buildUrl($original_uri);
+    $url = file_url_transform_relative($style->buildUrl($original_uri));
 
     // Create a test entity with the image field set.
     $entity = entity_create('entity_test');
@@ -137,7 +137,7 @@ function testImageStyleTheme() {
     // Create a style.
     $style = ImageStyle::create(array('name' => 'image_test', 'label' => 'Test'));
     $style->save();
-    $url = $style->buildUrl($original_uri);
+    $url = file_url_transform_relative($style->buildUrl($original_uri));
 
     // Create the base element that we'll use in the tests below.
     $base_element = array(
diff --git a/core/modules/responsive_image/responsive_image.module b/core/modules/responsive_image/responsive_image.module
index d36782d70f76dfc65d95a0059d2e19f3dbc9003b..7df1da81a9f63cd8ff637108fa664cfb607eee8a 100644
--- a/core/modules/responsive_image/responsive_image.module
+++ b/core/modules/responsive_image/responsive_image.module
@@ -391,7 +391,7 @@ function responsive_image_build_source_attributes(ImageInterface $image, array $
           // Use the image width as key so we can sort the array later on.
           // Images within a srcset should be sorted from small to large, since
           // the first matching source will be used.
-          $srcset[intval($dimensions['width'])] = file_create_url(_responsive_image_image_style_url($image_style_name, $image->getSource())) . ' ' . $dimensions['width'] . 'w';
+          $srcset[intval($dimensions['width'])] = _responsive_image_image_style_url($image_style_name, $image->getSource()) . ' ' . $dimensions['width'] . 'w';
           $sizes = array_merge(explode(',', $image_style_mapping['image_mapping']['sizes']), $sizes);
         }
         break;
@@ -405,7 +405,7 @@ function responsive_image_build_source_attributes(ImageInterface $image, array $
         // be sorted from small to large, since the first matching source will
         // be used. We multiply it by 100 so multipliers with up to two decimals
         // can be used.
-        $srcset[intval(Unicode::substr($multiplier, 0, -1) * 100)] = file_create_url(_responsive_image_image_style_url($image_style_mapping['image_mapping'], $image->getSource())) . ' ' . $multiplier;
+        $srcset[intval(Unicode::substr($multiplier, 0, -1) * 100)] = _responsive_image_image_style_url($image_style_mapping['image_mapping'], $image->getSource()) . ' ' . $multiplier;
         break;
     }
   }
@@ -495,9 +495,9 @@ function _responsive_image_image_style_url($style_name, $path) {
   }
   $entity = ImageStyle::load($style_name);
   if ($entity instanceof Drupal\image\Entity\ImageStyle) {
-    return $entity->buildUrl($path);
+    return file_url_transform_relative($entity->buildUrl($path));
   }
-  return file_create_url($path);
+  return file_url_transform_relative(file_create_url($path));
 }
 
 /**
diff --git a/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php b/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php
index d1290cb2a5fb76db0176b86cef2f587fe91a3161..e66cb82255e1ab2b6c30a5f39ea10a414da790b5 100644
--- a/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php
+++ b/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php
@@ -230,7 +230,7 @@ public function viewElements(FieldItemListInterface $items, $langcode) {
     foreach ($files as $delta => $file) {
       // Link the <picture> element to the original file.
       if (isset($link_file)) {
-        $url = Url::fromUri(file_create_url($file->getFileUri()));
+        $url = file_url_transform_relative(file_create_url($file->getFileUri()));
       }
       // Extract field item attributes for the theme function, and unset them
       // from the $item so that the field template does not re-render them.
diff --git a/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php b/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php
index f535f3f25cd5573a8a816a0d257ad83e5c34812a..e8e7aaee3ffbf775b8701c0dcba3a49ff92aeaf1 100644
--- a/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php
+++ b/core/modules/responsive_image/src/Tests/ResponsiveImageFieldDisplayTest.php
@@ -245,7 +245,7 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles =
     $display->setComponent($field_name, $display_options)
       ->save();
 
-    $default_output = '<a href="' . file_create_url($image_uri) . '"><picture';
+    $default_output = '<a href="' . file_url_transform_relative(file_create_url($image_uri)) . '"><picture';
     $this->drupalGet('node/' . $nid);
     $cache_tags_header = $this->drupalGetHeader('X-Drupal-Cache-Tags');
     $this->assertTrue(!preg_match('/ image_style\:/', $cache_tags_header), 'No image style cache tag found.');
@@ -290,10 +290,10 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles =
       $this->assertRaw('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
       $thumbnail_style = ImageStyle::load('thumbnail');
       // Assert the output of the 'srcset' attribute (small multipliers first).
-      $this->assertRaw('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== 1x, ' . $thumbnail_style->buildUrl($image_uri) . ' 1.5x');
+      $this->assertRaw('data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== 1x, ' . file_url_transform_relative($thumbnail_style->buildUrl($image_uri)) . ' 1.5x');
       $this->assertRaw('/styles/medium/');
       // Assert the output of the original image.
-      $this->assertRaw(file_create_url($image_uri) . ' 3x');
+      $this->assertRaw(file_url_transform_relative(file_create_url($image_uri)) . ' 3x');
       // Assert the output of the breakpoints.
       $this->assertRaw('media="(min-width: 0px)"');
       $this->assertRaw('media="(min-width: 560px)"');
@@ -302,7 +302,7 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles =
       $this->assertPattern('/media="\(min-width: 560px\)".+?sizes="\(min-width: 700px\) 700px, 100vw"/');
       // Assert the output of the 'srcset' attribute (small images first).
       $medium_style = ImageStyle::load('medium');
-      $this->assertRaw($medium_style->buildUrl($image_uri) . ' 220w, ' . $large_style->buildUrl($image_uri) . ' 360w');
+      $this->assertRaw(file_url_transform_relative($medium_style->buildUrl($image_uri)) . ' 220w, ' . file_url_transform_relative($large_style->buildUrl($image_uri)) . ' 360w');
       $this->assertRaw('media="(min-width: 851px)"');
     }
     $this->assertRaw('/styles/large/');
@@ -322,7 +322,7 @@ protected function doTestResponsiveImageFieldFormatters($scheme, $empty_styles =
       '#alt' => $alt,
       '#srcset' => array(
         array(
-          'uri' => $large_style->buildUrl($image->getSource()),
+          'uri' => file_url_transform_relative($large_style->buildUrl($image->getSource())),
         ),
       ),
     );
@@ -404,7 +404,7 @@ public function testResponsiveImageFieldFormattersEmptyMediaQuery() {
     $thumbnail_style = ImageStyle::load('thumbnail');
     $node = $node_storage->load($nid);
     $image_uri = File::load($node->{$field_name}->target_id)->getFileUri();
-    $this->assertPattern('/srcset="' . preg_quote($thumbnail_style->buildUrl($image_uri), '/') . ' 1x".+?media="\(min-width: 0px\)"/');
+    $this->assertPattern('/srcset="' . preg_quote(file_url_transform_relative($thumbnail_style->buildUrl($image_uri)), '/') . ' 1x".+?media="\(min-width: 0px\)"/');
   }
 
   /**
@@ -450,7 +450,7 @@ public function testResponsiveImageFieldFormattersOneSource() {
     $medium_style = ImageStyle::load('medium');
     $node = $node_storage->load($nid);
     $image_uri = File::load($node->{$field_name}->target_id)->getFileUri();
-    $this->assertRaw('<img srcset="' . $medium_style->buildUrl($image_uri) . ' 1x, ' . $large_style->buildUrl($image_uri) . ' 2x"');
+    $this->assertRaw('<img srcset="' . file_url_transform_relative($medium_style->buildUrl($image_uri)) . ' 1x, ' . file_url_transform_relative($large_style->buildUrl($image_uri)) . ' 2x"');
   }
 
   /**
@@ -510,7 +510,7 @@ private function assertResponsiveImageFieldFormattersLink($link_type) {
     switch ($link_type) {
       case 'file':
         // Make sure the link to the file is present.
-        $this->assertPattern('/<a(.*?)href="' . preg_quote(file_create_url($image_uri), '/') . '"(.*?)><picture/');
+        $this->assertPattern('/<a(.*?)href="' . preg_quote(file_url_transform_relative(file_create_url($image_uri)), '/') . '"(.*?)><picture/');
         break;
 
       case 'content':
diff --git a/core/modules/simpletest/src/Tests/SimpleTestTest.php b/core/modules/simpletest/src/Tests/SimpleTestTest.php
index 41d114ea6d10ef9c9c37d2efdcb5d858f9cd5bb6..812c1b249ac768efe7775ac4e17140037c74b124 100644
--- a/core/modules/simpletest/src/Tests/SimpleTestTest.php
+++ b/core/modules/simpletest/src/Tests/SimpleTestTest.php
@@ -333,7 +333,7 @@ function getTestResults() {
           $assertion['file'] = $this->asText($row->td[2]);
           $assertion['line'] = $this->asText($row->td[3]);
           $assertion['function'] = $this->asText($row->td[4]);
-          $ok_url = file_create_url('core/misc/icons/73b355/check.svg');
+          $ok_url = file_url_transform_relative(file_create_url('core/misc/icons/73b355/check.svg'));
           $assertion['status'] = ($row->td[5]->img['src'] == $ok_url) ? 'Pass' : 'Fail';
           $results['assertions'][] = $assertion;
         }
diff --git a/core/modules/system/src/Tests/Common/AttachedAssetsTest.php b/core/modules/system/src/Tests/Common/AttachedAssetsTest.php
index e3a516e322183326755671d5a903c64dd9c920ec..3ab2d31520cf7d6ad2a9b40bf0c79b936cecc1f7 100644
--- a/core/modules/system/src/Tests/Common/AttachedAssetsTest.php
+++ b/core/modules/system/src/Tests/Common/AttachedAssetsTest.php
@@ -96,8 +96,8 @@ function testAddFiles() {
     $rendered_css = $this->renderer->renderPlain($css_render_array);
     $rendered_js = $this->renderer->renderPlain($js_render_array);
     $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
-    $this->assertNotIdentical(strpos($rendered_css, '<link rel="stylesheet" href="' . file_create_url('core/modules/system/tests/modules/common_test/bar.css') . '?' . $query_string . '" media="all" />'), FALSE, 'Rendering an external CSS file.');
-    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/foo.js') . '?' . $query_string . '"></script>'), FALSE, 'Rendering an external JavaScript file.');
+    $this->assertNotIdentical(strpos($rendered_css, '<link rel="stylesheet" href="' . file_url_transform_relative(file_create_url('core/modules/system/tests/modules/common_test/bar.css')) . '?' . $query_string . '" media="all" />'), FALSE, 'Rendering an external CSS file.');
+    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_url_transform_relative(file_create_url('core/modules/system/tests/modules/common_test/foo.js')) . '?' . $query_string . '"></script>'), FALSE, 'Rendering an external JavaScript file.');
   }
 
   /**
@@ -150,7 +150,7 @@ function testAttributes() {
     $js_render_array = \Drupal::service('asset.js.collection_renderer')->render($js);
     $rendered_js = $this->renderer->renderPlain($js_render_array);
     $expected_1 = '<script src="http://example.com/deferred-external.js" foo="bar" defer></script>';
-    $expected_2 = '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/deferred-internal.js') . '?v=1" defer bar="foo"></script>';
+    $expected_2 = '<script src="' . file_url_transform_relative(file_create_url('core/modules/system/tests/modules/common_test/deferred-internal.js')) . '?v=1" defer bar="foo"></script>';
     $this->assertNotIdentical(strpos($rendered_js, $expected_1), FALSE, 'Rendered external JavaScript with correct defer and random attributes.');
     $this->assertNotIdentical(strpos($rendered_js, $expected_2), FALSE, 'Rendered internal JavaScript with correct defer and random attributes.');
   }
@@ -166,7 +166,7 @@ function testAggregatedAttributes() {
     $js_render_array = \Drupal::service('asset.js.collection_renderer')->render($js);
     $rendered_js = $this->renderer->renderPlain($js_render_array);
     $expected_1 = '<script src="http://example.com/deferred-external.js" foo="bar" defer></script>';
-    $expected_2 = '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/deferred-internal.js') . '?v=1" defer bar="foo"></script>';
+    $expected_2 = '<script src="' . file_url_transform_relative(file_create_url('core/modules/system/tests/modules/common_test/deferred-internal.js')) . '?v=1" defer bar="foo"></script>';
     $this->assertNotIdentical(strpos($rendered_js, $expected_1), FALSE, 'Rendered external JavaScript with correct defer and random attributes.');
     $this->assertNotIdentical(strpos($rendered_js, $expected_2), FALSE, 'Rendered internal JavaScript with correct defer and random attributes.');
   }
@@ -186,7 +186,7 @@ function testAggregation() {
     $rendered_footer_js = \Drupal::service('asset.js.collection_renderer')->render($footer_js);
     $this->assertEqual(2, count($rendered_footer_js), 'There are 2 JavaScript assets in the footer.');
     $this->assertEqual('drupal-settings-json', $rendered_footer_js[0]['#attributes']['data-drupal-selector'], 'The first of the two JavaScript assets in the footer has drupal settings.');
-    $this->assertEqual('http://', substr($rendered_footer_js[1]['#attributes']['src'], 0, 7), 'The second of the two JavaScript assets in the footer has the sole aggregated JavaScript asset.');
+    $this->assertEqual(0, strpos($rendered_footer_js[1]['#attributes']['src'], base_path()), 'The second of the two JavaScript assets in the footer has the sole aggregated JavaScript asset.');
   }
 
   /**
@@ -237,9 +237,9 @@ function testHeaderHTML() {
     $js_render_array = \Drupal::service('asset.js.collection_renderer')->render($js);
     $rendered_js = $this->renderer->renderPlain($js_render_array);
     $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
-    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/header.js') . '?' . $query_string . '"></script>'), FALSE, 'The JS asset in common_test/js-header appears in the header.');
-    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_create_url('core/misc/drupal.js')), FALSE, 'The JS asset of the direct dependency (core/drupal) of common_test/js-header appears in the header.');
-    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_create_url('core/assets/vendor/domready/ready.min.js')), FALSE, 'The JS asset of the indirect dependency (core/domready) of common_test/js-header appears in the header.');
+    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_url_transform_relative(file_create_url('core/modules/system/tests/modules/common_test/header.js')) . '?' . $query_string . '"></script>'), FALSE, 'The JS asset in common_test/js-header appears in the header.');
+    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_url_transform_relative(file_create_url('core/misc/drupal.js'))), FALSE, 'The JS asset of the direct dependency (core/drupal) of common_test/js-header appears in the header.');
+    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_url_transform_relative(file_create_url('core/assets/vendor/domready/ready.min.js'))), FALSE, 'The JS asset of the indirect dependency (core/domready) of common_test/js-header appears in the header.');
   }
 
   /**
@@ -267,8 +267,8 @@ function testBrowserConditionalComments() {
     $js = $this->assetResolver->getJsAssets($assets, FALSE)[1];
     $js_render_array = \Drupal::service('asset.js.collection_renderer')->render($js);
     $rendered_js = $this->renderer->renderPlain($js_render_array);
-    $expected_1 = "<!--[if lte IE 8]>\n" . '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/old-ie.js') . '?' . $default_query_string . '"></script>' . "\n<![endif]-->";
-    $expected_2 = "<!--[if !IE]><!-->\n" . '<script src="' . file_create_url('core/modules/system/tests/modules/common_test/no-ie.js') . '?' . $default_query_string . '"></script>' . "\n<!--<![endif]-->";
+    $expected_1 = "<!--[if lte IE 8]>\n" . '<script src="' . file_url_transform_relative(file_create_url('core/modules/system/tests/modules/common_test/old-ie.js')) . '?' . $default_query_string . '"></script>' . "\n<![endif]-->";
+    $expected_2 = "<!--[if !IE]><!-->\n" . '<script src="' . file_url_transform_relative(file_create_url('core/modules/system/tests/modules/common_test/no-ie.js')) . '?' . $default_query_string . '"></script>' . "\n<!--<![endif]-->";
 
     $this->assertNotIdentical(strpos($rendered_js, $expected_1), FALSE, 'Rendered JavaScript within downlevel-hidden conditional comments.');
     $this->assertNotIdentical(strpos($rendered_js, $expected_2), FALSE, 'Rendered JavaScript within downlevel-revealed conditional comments.');
@@ -476,8 +476,8 @@ function testAddJsFileWithQueryString() {
     $js_render_array = \Drupal::service('asset.js.collection_renderer')->render($js);
     $rendered_js = $this->renderer->renderPlain($js_render_array);
     $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
-    $this->assertNotIdentical(strpos($rendered_css, '<link rel="stylesheet" href="' . str_replace('&', '&amp;', file_create_url('core/modules/system/tests/modules/common_test/querystring.css?arg1=value1&arg2=value2')) . '&amp;' . $query_string . '" media="all" />'), FALSE, 'CSS file with query string gets version query string correctly appended..');
-    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . str_replace('&', '&amp;', file_create_url('core/modules/system/tests/modules/common_test/querystring.js?arg1=value1&arg2=value2')) . '&amp;' . $query_string . '"></script>'), FALSE, 'JavaScript file with query string gets version query string correctly appended.');
+    $this->assertNotIdentical(strpos($rendered_css, '<link rel="stylesheet" href="' . str_replace('&', '&amp;', file_url_transform_relative(file_create_url('core/modules/system/tests/modules/common_test/querystring.css?arg1=value1&arg2=value2'))) . '&amp;' . $query_string . '" media="all" />'), FALSE, 'CSS file with query string gets version query string correctly appended..');
+    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . str_replace('&', '&amp;', file_url_transform_relative(file_create_url('core/modules/system/tests/modules/common_test/querystring.js?arg1=value1&arg2=value2'))) . '&amp;' . $query_string . '"></script>'), FALSE, 'JavaScript file with query string gets version query string correctly appended.');
   }
 
 }
diff --git a/core/modules/system/src/Tests/System/ThemeTest.php b/core/modules/system/src/Tests/System/ThemeTest.php
index 5a079ec18c5e83ec4e5caa243768f66c4a6ec13c..c2f5a5750685c6c6609e51fe01ac4803bff5a98c 100644
--- a/core/modules/system/src/Tests/System/ThemeTest.php
+++ b/core/modules/system/src/Tests/System/ThemeTest.php
@@ -65,27 +65,27 @@ function testThemeSettings() {
       // Raw stream wrapper URI.
       $file->uri => array(
         'form' => file_uri_target($file->uri),
-        'src' => file_create_url($file->uri),
+        'src' => file_url_transform_relative(file_create_url($file->uri)),
       ),
       // Relative path within the public filesystem.
       file_uri_target($file->uri) => array(
         'form' => file_uri_target($file->uri),
-        'src' => file_create_url($file->uri),
+        'src' => file_url_transform_relative(file_create_url($file->uri)),
       ),
       // Relative path to a public file.
       $file_relative => array(
         'form' => $file_relative,
-        'src' => file_create_url($file->uri),
+        'src' => file_url_transform_relative(file_create_url($file->uri)),
       ),
       // Relative path to an arbitrary file.
       'core/misc/druplicon.png' => array(
         'form' => 'core/misc/druplicon.png',
-        'src' => $GLOBALS['base_url'] . '/' . 'core/misc/druplicon.png',
+        'src' => base_path() . 'core/misc/druplicon.png',
       ),
       // Relative path to a file in a theme.
       $default_theme_path . '/logo.svg' => array(
         'form' => $default_theme_path . '/logo.svg',
-        'src' => $GLOBALS['base_url'] . '/' . $default_theme_path . '/logo.svg',
+        'src' => base_path() . $default_theme_path . '/logo.svg',
       ),
     );
     foreach ($supported_paths as $input => $expected) {
@@ -186,7 +186,7 @@ function testThemeSettings() {
         ':rel' => 'home',
       )
     );
-    $this->assertEqual($elements[0]['src'], file_create_url($uploaded_filename));
+    $this->assertEqual($elements[0]['src'], file_url_transform_relative(file_create_url($uploaded_filename)));
 
     $this->container->get('theme_handler')->install(array('bartik'));
 
diff --git a/core/modules/system/src/Tests/Theme/EngineTwigTest.php b/core/modules/system/src/Tests/Theme/EngineTwigTest.php
index 283b41d4b502f642590122ee8f8136656c16840b..4e2e563af7bbef7bf0bfae3dd87c25a5f097fd5a 100644
--- a/core/modules/system/src/Tests/Theme/EngineTwigTest.php
+++ b/core/modules/system/src/Tests/Theme/EngineTwigTest.php
@@ -125,7 +125,7 @@ public function testTwigUrlToString() {
    */
   public function testTwigFileUrls() {
     $this->drupalGet('/twig-theme-test/file-url');
-    $filepath = file_create_url('core/modules/system/tests/modules/twig_theme_test/twig_theme_test.js');
+    $filepath = file_url_transform_relative(file_create_url('core/modules/system/tests/modules/twig_theme_test/twig_theme_test.js'));
     $this->assertRaw('<div>file_url: ' . $filepath . '</div>');
   }
 
diff --git a/core/modules/system/src/Tests/Theme/ImageTest.php b/core/modules/system/src/Tests/Theme/ImageTest.php
index 87b403c75a005aed542fa1f3f0019008689ff107..d0f93df20d7da633f7eb82b2980cbc5db2577815 100644
--- a/core/modules/system/src/Tests/Theme/ImageTest.php
+++ b/core/modules/system/src/Tests/Theme/ImageTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Tests\Theme;
 
 use Drupal\simpletest\KernelTestBase;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Tests built-in image theme functions.
@@ -32,9 +33,17 @@ class ImageTest extends KernelTestBase {
 
   protected function setUp() {
     parent::setUp();
+
+    // The code under test uses file_url_transform_relative(), which relies on
+    // the Request containing the correct hostname. KernelTestBase doesn't set
+    // it, so push another request onto the stack to ensure it's correct.
+    $request = Request::create('/', 'GET', [], [], [], $_SERVER);
+    $this->container = $this->kernel->getContainer();
+    $this->container->get('request_stack')->push($request);
+
     $this->testImages = array(
-      '/core/misc/druplicon.png',
-      '/core/misc/loading.gif',
+      'core/misc/druplicon.png',
+      'core/misc/loading.gif',
     );
   }
 
@@ -75,7 +84,7 @@ function testThemeImageWithSrc() {
     $this->render($image);
 
     // Make sure the src attribute has the correct value.
-    $this->assertRaw(file_create_url($image['#uri']), 'Correct output for an image with the src attribute.');
+    $this->assertRaw(file_url_transform_relative(file_create_url($image['#uri'])), 'Correct output for an image with the src attribute.');
   }
 
   /**
@@ -103,7 +112,7 @@ function testThemeImageWithSrcsetMultiplier() {
     $this->render($image);
 
     // Make sure the srcset attribute has the correct value.
-    $this->assertRaw(file_create_url($this->testImages[0]) . ' 1x, ' . file_create_url($this->testImages[1]) . ' 2x', 'Correct output for image with srcset attribute and multipliers.');
+    $this->assertRaw(file_url_transform_relative(file_create_url($this->testImages[0])) . ' 1x, ' . file_url_transform_relative(file_create_url($this->testImages[1])) . ' 2x', 'Correct output for image with srcset attribute and multipliers.');
   }
 
   /**
@@ -135,7 +144,7 @@ function testThemeImageWithSrcsetWidth() {
     $this->render($image);
 
     // Make sure the srcset attribute has the correct value.
-    $this->assertRaw(file_create_url($this->testImages[0]) . ' ' . $widths[0] . ', ' . file_create_url($this->testImages[1]) . ' ' . $widths[1], 'Correct output for image with srcset attribute and width descriptors.');
+    $this->assertRaw(file_url_transform_relative(file_create_url($this->testImages[0])) . ' ' . $widths[0] . ', ' . file_url_transform_relative(file_create_url($this->testImages[1])) . ' ' . $widths[1], 'Correct output for image with srcset attribute and width descriptors.');
   }
 
 }
diff --git a/core/modules/system/src/Tests/Update/UpdatePathTestJavaScriptTest.php b/core/modules/system/src/Tests/Update/UpdatePathTestJavaScriptTest.php
index f7ff4c336f9be787e2b53708f30eeb990a9755b6..d949dae7315c892b57855568deb613c0a1ec7338 100644
--- a/core/modules/system/src/Tests/Update/UpdatePathTestJavaScriptTest.php
+++ b/core/modules/system/src/Tests/Update/UpdatePathTestJavaScriptTest.php
@@ -43,7 +43,9 @@ protected function doSelectionTest() {
       if (!isset($script['src'])) {
         continue;
       }
-      $src = (string) $script['src'];
+      // Source is a root-relative URL. Transform it to an absolute URL to allow
+      // file_get_contents() to access the file.
+      $src = preg_replace('#^' . $GLOBALS['base_path'] . '(.*)#i', $GLOBALS['base_url'] . '/' . '${1}', (string) $script['src']);
       $file_content = file_get_contents($src);
 
       if (strpos($file_content, 'window.drupalSettings =') !== FALSE) {
diff --git a/core/modules/user/src/Tests/UserPictureTest.php b/core/modules/user/src/Tests/UserPictureTest.php
index bd28934e64998ab0d39da543f0b65a901e7bd848..9fa28a355b3daffe5efa49854a5702b7fcc9daff 100644
--- a/core/modules/user/src/Tests/UserPictureTest.php
+++ b/core/modules/user/src/Tests/UserPictureTest.php
@@ -100,7 +100,7 @@ function testPictureOnNodeComment() {
 
     $image_style_id = $this->config('core.entity_view_display.user.user.compact')->get('content.user_picture.settings.image_style');
     $style = ImageStyle::load($image_style_id);
-    $image_url = $style->buildUrl($file->getfileUri());
+    $image_url = file_url_transform_relative($style->buildUrl($file->getfileUri()));
     $alt_text = 'Profile picture for user ' . $this->webUser->getUsername();
 
     // Verify that the image is displayed on the node page.
diff --git a/core/tests/Drupal/Tests/Core/Asset/CssCollectionRendererUnitTest.php b/core/tests/Drupal/Tests/Core/Asset/CssCollectionRendererUnitTest.php
index eab4fe4cd8b92f1bb12017969b0b7823e5e6ec63..48a92ee1e12c3baf9af1dee2d820c0204cd7dbae 100644
--- a/core/tests/Drupal/Tests/Core/Asset/CssCollectionRendererUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/CssCollectionRendererUnitTest.php
@@ -9,9 +9,9 @@
 namespace {
 
 /**
- * CssRenderer uses file_create_url(), which *is* available when using the
- * Simpletest test runner, but not when using the PHPUnit test runner; hence
- * this hack.
+ * CssCollectionRenderer uses file_create_url() & file_url_transform_relative(),
+ * which *are* available when using the Simpletest test runner, but not when
+ * using the PHPUnit test runner; hence this hack.
  */
 if (!function_exists('file_create_url')) {
 
@@ -23,6 +23,17 @@ function file_create_url($uri) {
     return 'file_create_url:' . $uri;
   }
 
+}
+if (!function_exists('file_url_transform_relative')) {
+
+  /**
+   * Temporary mock of file_url_transform_relative, until that is moved into
+   * Component/Utility.
+   */
+  function file_url_transform_relative($uri) {
+    return 'file_url_transform_relative:' . $uri;
+  }
+
 }
 
 }
@@ -153,7 +164,7 @@ function providerTestRender() {
           0 => array('group' => 0, 'type' => 'file', 'media' => 'all', 'preprocess' => TRUE, 'data' => 'public://css/file-all', 'browsers' => array()),
         ),
         array(
-          0 => $create_link_element(file_create_url('public://css/file-all') . '?0', 'all'),
+          0 => $create_link_element(file_url_transform_relative(file_create_url('public://css/file-all')) . '?0', 'all'),
         ),
       ),
       // 31 file CSS assets: expect 31 link elements.
@@ -192,37 +203,37 @@ function providerTestRender() {
           30 => $create_file_css_asset('public://css/31.css'),
         ),
         array(
-          0 => $create_link_element(file_create_url('public://css/1.css') . '?0'),
-          1 => $create_link_element(file_create_url('public://css/2.css') . '?0'),
-          2 => $create_link_element(file_create_url('public://css/3.css') . '?0'),
-          3 => $create_link_element(file_create_url('public://css/4.css') . '?0'),
-          4 => $create_link_element(file_create_url('public://css/5.css') . '?0'),
-          5 => $create_link_element(file_create_url('public://css/6.css') . '?0'),
-          6 => $create_link_element(file_create_url('public://css/7.css') . '?0'),
-          7 => $create_link_element(file_create_url('public://css/8.css') . '?0'),
-          8 => $create_link_element(file_create_url('public://css/9.css') . '?0'),
-          9 => $create_link_element(file_create_url('public://css/10.css') . '?0'),
-          10 => $create_link_element(file_create_url('public://css/11.css') . '?0'),
-          11 => $create_link_element(file_create_url('public://css/12.css') . '?0'),
-          12 => $create_link_element(file_create_url('public://css/13.css') . '?0'),
-          13 => $create_link_element(file_create_url('public://css/14.css') . '?0'),
-          14 => $create_link_element(file_create_url('public://css/15.css') . '?0'),
-          15 => $create_link_element(file_create_url('public://css/16.css') . '?0'),
-          16 => $create_link_element(file_create_url('public://css/17.css') . '?0'),
-          17 => $create_link_element(file_create_url('public://css/18.css') . '?0'),
-          18 => $create_link_element(file_create_url('public://css/19.css') . '?0'),
-          19 => $create_link_element(file_create_url('public://css/20.css') . '?0'),
-          20 => $create_link_element(file_create_url('public://css/21.css') . '?0'),
-          21 => $create_link_element(file_create_url('public://css/22.css') . '?0'),
-          22 => $create_link_element(file_create_url('public://css/23.css') . '?0'),
-          23 => $create_link_element(file_create_url('public://css/24.css') . '?0'),
-          24 => $create_link_element(file_create_url('public://css/25.css') . '?0'),
-          25 => $create_link_element(file_create_url('public://css/26.css') . '?0'),
-          26 => $create_link_element(file_create_url('public://css/27.css') . '?0'),
-          27 => $create_link_element(file_create_url('public://css/28.css') . '?0'),
-          28 => $create_link_element(file_create_url('public://css/29.css') . '?0'),
-          29 => $create_link_element(file_create_url('public://css/30.css') . '?0'),
-          30 => $create_link_element(file_create_url('public://css/31.css') . '?0'),
+          0 => $create_link_element(file_url_transform_relative(file_create_url('public://css/1.css')) . '?0'),
+          1 => $create_link_element(file_url_transform_relative(file_create_url('public://css/2.css')) . '?0'),
+          2 => $create_link_element(file_url_transform_relative(file_create_url('public://css/3.css')) . '?0'),
+          3 => $create_link_element(file_url_transform_relative(file_create_url('public://css/4.css')) . '?0'),
+          4 => $create_link_element(file_url_transform_relative(file_create_url('public://css/5.css')) . '?0'),
+          5 => $create_link_element(file_url_transform_relative(file_create_url('public://css/6.css')) . '?0'),
+          6 => $create_link_element(file_url_transform_relative(file_create_url('public://css/7.css')) . '?0'),
+          7 => $create_link_element(file_url_transform_relative(file_create_url('public://css/8.css')) . '?0'),
+          8 => $create_link_element(file_url_transform_relative(file_create_url('public://css/9.css')) . '?0'),
+          9 => $create_link_element(file_url_transform_relative(file_create_url('public://css/10.css')) . '?0'),
+          10 => $create_link_element(file_url_transform_relative(file_create_url('public://css/11.css')) . '?0'),
+          11 => $create_link_element(file_url_transform_relative(file_create_url('public://css/12.css')) . '?0'),
+          12 => $create_link_element(file_url_transform_relative(file_create_url('public://css/13.css')) . '?0'),
+          13 => $create_link_element(file_url_transform_relative(file_create_url('public://css/14.css')) . '?0'),
+          14 => $create_link_element(file_url_transform_relative(file_create_url('public://css/15.css')) . '?0'),
+          15 => $create_link_element(file_url_transform_relative(file_create_url('public://css/16.css')) . '?0'),
+          16 => $create_link_element(file_url_transform_relative(file_create_url('public://css/17.css')) . '?0'),
+          17 => $create_link_element(file_url_transform_relative(file_create_url('public://css/18.css')) . '?0'),
+          18 => $create_link_element(file_url_transform_relative(file_create_url('public://css/19.css')) . '?0'),
+          19 => $create_link_element(file_url_transform_relative(file_create_url('public://css/20.css')) . '?0'),
+          20 => $create_link_element(file_url_transform_relative(file_create_url('public://css/21.css')) . '?0'),
+          21 => $create_link_element(file_url_transform_relative(file_create_url('public://css/22.css')) . '?0'),
+          22 => $create_link_element(file_url_transform_relative(file_create_url('public://css/23.css')) . '?0'),
+          23 => $create_link_element(file_url_transform_relative(file_create_url('public://css/24.css')) . '?0'),
+          24 => $create_link_element(file_url_transform_relative(file_create_url('public://css/25.css')) . '?0'),
+          25 => $create_link_element(file_url_transform_relative(file_create_url('public://css/26.css')) . '?0'),
+          26 => $create_link_element(file_url_transform_relative(file_create_url('public://css/27.css')) . '?0'),
+          27 => $create_link_element(file_url_transform_relative(file_create_url('public://css/28.css')) . '?0'),
+          28 => $create_link_element(file_url_transform_relative(file_create_url('public://css/29.css')) . '?0'),
+          29 => $create_link_element(file_url_transform_relative(file_create_url('public://css/30.css')) . '?0'),
+          30 => $create_link_element(file_url_transform_relative(file_create_url('public://css/31.css')) . '?0'),
         ),
       ),
       // 32 file CSS assets with the same properties: expect 2 style elements.
@@ -263,40 +274,40 @@ function providerTestRender() {
         ),
         array(
           0 => $create_style_element('
-@import url("' . file_create_url('public://css/1.css') . '?0");
-@import url("' . file_create_url('public://css/2.css') . '?0");
-@import url("' . file_create_url('public://css/3.css') . '?0");
-@import url("' . file_create_url('public://css/4.css') . '?0");
-@import url("' . file_create_url('public://css/5.css') . '?0");
-@import url("' . file_create_url('public://css/6.css') . '?0");
-@import url("' . file_create_url('public://css/7.css') . '?0");
-@import url("' . file_create_url('public://css/8.css') . '?0");
-@import url("' . file_create_url('public://css/9.css') . '?0");
-@import url("' . file_create_url('public://css/10.css') . '?0");
-@import url("' . file_create_url('public://css/11.css') . '?0");
-@import url("' . file_create_url('public://css/12.css') . '?0");
-@import url("' . file_create_url('public://css/13.css') . '?0");
-@import url("' . file_create_url('public://css/14.css') . '?0");
-@import url("' . file_create_url('public://css/15.css') . '?0");
-@import url("' . file_create_url('public://css/16.css') . '?0");
-@import url("' . file_create_url('public://css/17.css') . '?0");
-@import url("' . file_create_url('public://css/18.css') . '?0");
-@import url("' . file_create_url('public://css/19.css') . '?0");
-@import url("' . file_create_url('public://css/20.css') . '?0");
-@import url("' . file_create_url('public://css/21.css') . '?0");
-@import url("' . file_create_url('public://css/22.css') . '?0");
-@import url("' . file_create_url('public://css/23.css') . '?0");
-@import url("' . file_create_url('public://css/24.css') . '?0");
-@import url("' . file_create_url('public://css/25.css') . '?0");
-@import url("' . file_create_url('public://css/26.css') . '?0");
-@import url("' . file_create_url('public://css/27.css') . '?0");
-@import url("' . file_create_url('public://css/28.css') . '?0");
-@import url("' . file_create_url('public://css/29.css') . '?0");
-@import url("' . file_create_url('public://css/30.css') . '?0");
-@import url("' . file_create_url('public://css/31.css') . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/1.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/2.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/3.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/4.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/5.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/6.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/7.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/8.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/9.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/10.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/11.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/12.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/13.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/14.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/15.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/16.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/17.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/18.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/19.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/20.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/21.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/22.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/23.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/24.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/25.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/26.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/27.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/28.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/29.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/30.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/31.css')) . '?0");
 ', 'all'),
           1 => $create_style_element('
-@import url("' . file_create_url('public://css/32.css') . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/32.css')) . '?0");
 ', 'all'),
         ),
       ),
@@ -340,46 +351,46 @@ function providerTestRender() {
         ),
         array(
           0 => $create_style_element('
-@import url("' . file_create_url('public://css/1.css') . '?0");
-@import url("' . file_create_url('public://css/2.css') . '?0");
-@import url("' . file_create_url('public://css/3.css') . '?0");
-@import url("' . file_create_url('public://css/4.css') . '?0");
-@import url("' . file_create_url('public://css/5.css') . '?0");
-@import url("' . file_create_url('public://css/6.css') . '?0");
-@import url("' . file_create_url('public://css/7.css') . '?0");
-@import url("' . file_create_url('public://css/8.css') . '?0");
-@import url("' . file_create_url('public://css/9.css') . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/1.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/2.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/3.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/4.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/5.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/6.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/7.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/8.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/9.css')) . '?0");
 ', 'all'),
           1 => $create_style_element('
-@import url("' . file_create_url('public://css/10.css') . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/10.css')) . '?0");
 ', 'screen'),
           2 => $create_style_element('
-@import url("' . file_create_url('public://css/11.css') . '?0");
-@import url("' . file_create_url('public://css/12.css') . '?0");
-@import url("' . file_create_url('public://css/13.css') . '?0");
-@import url("' . file_create_url('public://css/14.css') . '?0");
-@import url("' . file_create_url('public://css/15.css') . '?0");
-@import url("' . file_create_url('public://css/16.css') . '?0");
-@import url("' . file_create_url('public://css/17.css') . '?0");
-@import url("' . file_create_url('public://css/18.css') . '?0");
-@import url("' . file_create_url('public://css/19.css') . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/11.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/12.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/13.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/14.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/15.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/16.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/17.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/18.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/19.css')) . '?0");
 ', 'all'),
           3 => $create_style_element('
-@import url("' . file_create_url('public://css/20.css') . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/20.css')) . '?0");
 ', 'print'),
           4 => $create_style_element('
-@import url("' . file_create_url('public://css/21.css') . '?0");
-@import url("' . file_create_url('public://css/22.css') . '?0");
-@import url("' . file_create_url('public://css/23.css') . '?0");
-@import url("' . file_create_url('public://css/24.css') . '?0");
-@import url("' . file_create_url('public://css/25.css') . '?0");
-@import url("' . file_create_url('public://css/26.css') . '?0");
-@import url("' . file_create_url('public://css/27.css') . '?0");
-@import url("' . file_create_url('public://css/28.css') . '?0");
-@import url("' . file_create_url('public://css/29.css') . '?0");
-@import url("' . file_create_url('public://css/30.css') . '?0");
-@import url("' . file_create_url('public://css/31.css') . '?0");
-@import url("' . file_create_url('public://css/32.css') . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/21.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/22.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/23.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/24.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/25.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/26.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/27.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/28.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/29.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/30.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/31.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/32.css')) . '?0");
 ', 'all'),
         ),
       ),
@@ -422,40 +433,40 @@ function providerTestRender() {
         ),
         array(
           0 => $create_style_element('
-@import url("' . file_create_url('public://css/1.css') . '?0");
-@import url("' . file_create_url('public://css/2.css') . '?0");
-@import url("' . file_create_url('public://css/3.css') . '?0");
-@import url("' . file_create_url('public://css/4.css') . '?0");
-@import url("' . file_create_url('public://css/5.css') . '?0");
-@import url("' . file_create_url('public://css/6.css') . '?0");
-@import url("' . file_create_url('public://css/7.css') . '?0");
-@import url("' . file_create_url('public://css/8.css') . '?0");
-@import url("' . file_create_url('public://css/9.css') . '?0");
-@import url("' . file_create_url('public://css/10.css') . '?0");
-@import url("' . file_create_url('public://css/11.css') . '?0");
-@import url("' . file_create_url('public://css/12.css') . '?0");
-@import url("' . file_create_url('public://css/13.css') . '?0");
-@import url("' . file_create_url('public://css/14.css') . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/1.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/2.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/3.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/4.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/5.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/6.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/7.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/8.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/9.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/10.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/11.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/12.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/13.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/14.css')) . '?0");
 ', 'all'),
-          1 => $create_link_element(file_create_url('public://css/15.css') . '?0'),
+          1 => $create_link_element(file_url_transform_relative(file_create_url('public://css/15.css')) . '?0'),
           2 => $create_style_element('
-@import url("' . file_create_url('public://css/16.css') . '?0");
-@import url("' . file_create_url('public://css/17.css') . '?0");
-@import url("' . file_create_url('public://css/18.css') . '?0");
-@import url("' . file_create_url('public://css/19.css') . '?0");
-@import url("' . file_create_url('public://css/20.css') . '?0");
-@import url("' . file_create_url('public://css/21.css') . '?0");
-@import url("' . file_create_url('public://css/22.css') . '?0");
-@import url("' . file_create_url('public://css/23.css') . '?0");
-@import url("' . file_create_url('public://css/24.css') . '?0");
-@import url("' . file_create_url('public://css/25.css') . '?0");
-@import url("' . file_create_url('public://css/26.css') . '?0");
-@import url("' . file_create_url('public://css/27.css') . '?0");
-@import url("' . file_create_url('public://css/28.css') . '?0");
-@import url("' . file_create_url('public://css/29.css') . '?0");
-@import url("' . file_create_url('public://css/30.css') . '?0");
-@import url("' . file_create_url('public://css/31.css') . '?0");
-@import url("' . file_create_url('public://css/32.css') . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/16.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/17.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/18.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/19.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/20.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/21.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/22.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/23.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/24.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/25.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/26.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/27.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/28.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/29.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/30.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/31.css')) . '?0");
+@import url("' . file_url_transform_relative(file_create_url('public://css/32.css')) . '?0");
 ', 'all'),
         ),
       ),
diff --git a/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php b/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php
index 03bb980f32cc2a96fe97c9614a5132613664f8ce..5922bf1f67583bbdd07e54797554b5d596a46021 100644
--- a/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/CssOptimizerUnitTest.php
@@ -9,7 +9,8 @@
 namespace {
 
 /**
- * CssOptimizer uses file_create_url(), which *is* available when using the
+ * CssOptimizer uses file_create_url(), file_uri_scheme() and
+ * file_url_transform_relative(), which *are* available when using the
  * Simpletest test runner, but not when using the PHPUnit test runner; hence
  * this hack.
  */
@@ -31,6 +32,17 @@ function file_uri_scheme($uri) {
     return FALSE;
   }
 
+}
+if (!function_exists('file_url_transform_relative')) {
+
+  /**
+   * Temporary mock of file_url_transform_relative, until that is moved into
+   * Component/Utility.
+   */
+  function file_url_transform_relative($uri) {
+    return 'file_url_transform_relative:' . $uri;
+  }
+
 }
 
 }
@@ -48,6 +60,11 @@ function file_uri_scheme($uri) {
  */
 class CssOptimizerUnitTest extends UnitTestCase {
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $backupGlobals = FALSE;
+
   /**
    * A CSS asset optimizer.
    *
@@ -65,7 +82,8 @@ protected function setUp() {
    * Provides data for the CSS asset optimizing test.
    */
   function providerTestOptimize() {
-    $path = dirname(__FILE__)  . '/css_test_files/';
+    $path = 'core/tests/Drupal/Tests/Core/Asset/css_test_files/';
+    $absolute_path = dirname(__FILE__)  . '/css_test_files/';
     return array(
       // File. Tests:
       // - Stripped comments and white-space.
@@ -82,7 +100,7 @@ function providerTestOptimize() {
           'browsers' => array('IE' => TRUE, '!IE' => TRUE),
           'basename' => 'css_input_without_import.css',
         ),
-        file_get_contents($path . 'css_input_without_import.css.optimized.css'),
+        file_get_contents($absolute_path . 'css_input_without_import.css.optimized.css'),
       ),
       // File. Tests:
       // - Proper URLs in imported files. (https://www.drupal.org/node/265719)
@@ -102,7 +120,7 @@ function providerTestOptimize() {
           'browsers' => array('IE' => TRUE, '!IE' => TRUE),
           'basename' => 'css_input_with_import.css',
         ),
-        str_replace('url(images/icon.png)', 'url(' . file_create_url($path . 'images/icon.png') . ')', file_get_contents($path . 'css_input_with_import.css.optimized.css')),
+        str_replace('url(images/icon.png)', 'url(' . file_url_transform_relative(file_create_url($path . 'images/icon.png')) . ')', file_get_contents($absolute_path . 'css_input_with_import.css.optimized.css')),
       ),
       // File. Tests:
       // - Retain comment hacks.
@@ -117,7 +135,7 @@ function providerTestOptimize() {
           'browsers' => array('IE' => TRUE, '!IE' => TRUE),
           'basename' => 'comment_hacks.css',
         ),
-        file_get_contents($path . 'comment_hacks.css.optimized.css'),
+        file_get_contents($absolute_path . 'comment_hacks.css.optimized.css'),
       ),
       // File in subfolder. Tests:
       // - CSS import path is properly interpreted.
@@ -134,7 +152,7 @@ function providerTestOptimize() {
           'browsers' => array('IE' => TRUE, '!IE' => TRUE),
           'basename' => 'css_input_with_import.css',
         ),
-        str_replace('url(../images/icon.png)', 'url(' . file_create_url($path . 'images/icon.png') . ')', file_get_contents($path . 'css_subfolder/css_input_with_import.css.optimized.css')),
+        str_replace('url(../images/icon.png)', 'url(' . file_url_transform_relative(file_create_url($path . 'images/icon.png')) . ')', file_get_contents($absolute_path . 'css_subfolder/css_input_with_import.css.optimized.css')),
       ),
       // File. Tests:
       // - Any @charaset declaration at the beginning of a file should be
@@ -150,7 +168,7 @@ function providerTestOptimize() {
           'browsers' => array('IE' => TRUE, '!IE' => TRUE),
           'basename' => 'charset_sameline.css',
         ),
-        file_get_contents($path . 'charset.css.optimized.css'),
+        file_get_contents($absolute_path . 'charset.css.optimized.css'),
       ),
       array(
         array(
@@ -163,7 +181,7 @@ function providerTestOptimize() {
           'browsers' => array('IE' => TRUE, '!IE' => TRUE),
           'basename' => 'charset_newline.css',
         ),
-        file_get_contents($path . 'charset.css.optimized.css'),
+        file_get_contents($absolute_path . 'charset.css.optimized.css'),
       ),
       array(
         array(
@@ -226,7 +244,18 @@ function providerTestOptimize() {
    * @dataProvider providerTestOptimize
    */
   function testOptimize($css_asset, $expected) {
+    global $base_path;
+    $original_base_path = $base_path;
+    $base_path = '/';
+
+    // \Drupal\Core\Asset\CssOptimizer::loadFile() relies on the current working
+    // directory being the one that is used when index.php is the entry point.
+    // Note: PHPUnit automatically restores the original working directory.
+    chdir(realpath(__DIR__ . '/../../../../../../'));
+
     $this->assertEquals($expected, $this->optimizer->optimize($css_asset), 'Group of file CSS assets optimized correctly.');
+
+    $base_path = $original_base_path;
   }
 
   /**