diff --git a/core/core.services.yml b/core/core.services.yml
index 5ffa0d96f4d92ee014d4d8b6226a26caf3fc38d8..dedc278b68b0b12387e83dcf367265704ecd1dc6 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1649,7 +1649,7 @@ services:
   Drupal\Core\Session\MetadataBag: '@session_manager.metadata_bag'
   asset.css.collection_renderer:
     class: Drupal\Core\Asset\CssCollectionRenderer
-    arguments: [ '@asset.query_string', '@file_url_generator' ]
+    arguments: [ '@asset.query_string', '@file_url_generator' , '@current_route_match', '@request_stack']
   asset.css.collection_optimizer:
     class: Drupal\Core\Asset\CssCollectionOptimizerLazy
     arguments: [ '@asset.css.collection_grouper', '@asset.css.optimizer', '@theme.manager', '@library.dependency_resolver', '@request_stack', '@file_system', '@config.factory', '@file_url_generator', '@datetime.time', '@language_manager']
diff --git a/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php b/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
index 162a7bccbe8c0659710ddaac2b975819abd1012f..4aae4316ccab2a24818eb4b22275f3269a976d14 100644
--- a/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
+++ b/core/lib/Drupal/Core/Asset/CssCollectionRenderer.php
@@ -3,6 +3,9 @@
 namespace Drupal\Core\Asset;
 
 use Drupal\Core\File\FileUrlGeneratorInterface;
+use Drupal\Core\Render\Markup;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
 
 /**
  * Renders CSS assets.
@@ -16,10 +19,16 @@ class CssCollectionRenderer implements AssetCollectionRendererInterface {
    *   The asset query string.
    * @param \Drupal\Core\File\FileUrlGeneratorInterface $fileUrlGenerator
    *   The file URL generator.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
+   *   Current route match.
+   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
+   *   Request stack.
    */
   public function __construct(
     protected AssetQueryStringInterface $assetQueryString,
     protected FileUrlGeneratorInterface $fileUrlGenerator,
+    protected RouteMatchInterface $routeMatch,
+    protected RequestStack $requestStack,
   ) {
   }
 
@@ -76,7 +85,95 @@ public function render(array $css_assets) {
       $elements[] = $element;
     }
 
-    return $elements;
+    return $this->inlineCriticalCss($elements);
+  }
+
+  /**
+   * Uses an inline style tag for any CSS files that are flagged as critical.
+   *
+   * To make use of this, add {attributes: {critical: true} to CSS files in
+   * your theme or module's libraries.yml file. Be sure to mark the files as
+   * preprocess: false too so they're not aggregated.
+   *
+   * @param array $assets
+   *   Existing CSS elements.
+   *
+   * @return array
+   *   CSS elements with any CSS inlined as required.
+   */
+  protected function inlineCriticalCss(array $assets): array {
+    // Only inline CSS if we are using the frontend theme.
+    // Also skip anything other than HTML requests.
+    $request = $this->requestStack->getCurrentRequest();
+    $wrapperFormat = $request->get('_wrapper_format', 'html');
+    // Views AJAX is special and doesn't set wrapper_format properly, so check
+    // for that too.
+    $currentRoute = $this->routeMatch->getRouteName();
+    if (
+      // Not HTML.
+      $wrapperFormat !== 'html'
+      // OR views AJAX.
+      || $currentRoute === 'views.ajax'
+      // OR Big Pipe placeholders.
+      || $request->headers->get('accept') === 'application/vnd.drupal-ajax') {
+      return $assets;
+    }
+
+    $elements = [];
+    foreach ($assets as $asset) {
+      $attributes = $asset['#attributes'];
+      // Skip files with print media.
+      if ($asset['#attributes']['media'] === 'print') {
+        $elements[] = $asset;
+        continue;
+      }
+      // Any CSS file with a critical flag should be inlined.
+      if (isset($attributes['critical'])) {
+        $inlineCriticalCSS = $this->inlineCssFile(\substr($attributes['href'], 1));
+        if ($inlineCriticalCSS !== NULL) {
+          $elements[] = $inlineCriticalCSS;
+          continue;
+        }
+      }
+      // @todo Defer all non critical CSS -
+      //   https://www.drupal.org/project/drupal/issues/2989324
+      $elements[] = $asset;
+    }
+
+    return \array_filter($elements);
+  }
+
+  /**
+   * Turn a file into a renderable <style> tag.
+   *
+   * @param string $path
+   *   File URL to turn into inline CSS.
+   *
+   * @return array|null
+   *   Return NULL if the file does not exist.
+   */
+  protected function inlineCssFile(string $path): ?array {
+    $path = \strtok($path, "?");
+    if (!\is_string($path)) {
+      return NULL;
+    }
+    $file_name = \sprintf('%s/%s', DRUPAL_ROOT, $path);
+    if (\file_exists($file_name)) {
+      $contents = \file_get_contents($path);
+      if (!\is_string($contents)) {
+        return NULL;
+      }
+      return [
+        '#type' => 'html_tag',
+        '#tag' => 'style',
+        '#value' => Markup::create($contents),
+        '#attributes' => [
+          // Add a data-src attribute to aid in debugging/identification.
+          'data-src' => \basename($path),
+        ],
+      ];
+    }
+    return NULL;
   }
 
 }
diff --git a/core/tests/Drupal/FunctionalTests/Theme/OliveroTest.php b/core/tests/Drupal/FunctionalTests/Theme/OliveroTest.php
index c3be4d60279e8b70c7b56f40864834b85698578a..d63440da66642e7d37b7601cd1e5c50ba4d443a3 100644
--- a/core/tests/Drupal/FunctionalTests/Theme/OliveroTest.php
+++ b/core/tests/Drupal/FunctionalTests/Theme/OliveroTest.php
@@ -41,7 +41,7 @@ class OliveroTest extends BrowserTestBase {
   public function testBaseLibraryAvailable(): void {
     $this->drupalGet('');
     $this->assertSession()->statusCodeEquals(200);
-    $this->assertSession()->responseContains('olivero/css/base/base.css');
+    $this->assertSession()->elementExists('css', 'style[data-src="base.css"]');
     $this->assertSession()->responseContains('olivero/js/navigation-utils.js');
   }
 
diff --git a/core/themes/olivero/olivero.libraries.yml b/core/themes/olivero/olivero.libraries.yml
index d759787b762a06086c749edab10fb77b4936ff27..0478b8efd268c66bc966a8b673638a271ce12d3c 100644
--- a/core/themes/olivero/olivero.libraries.yml
+++ b/core/themes/olivero/olivero.libraries.yml
@@ -2,12 +2,12 @@ global-styling:
   version: VERSION
   css:
     base:
-      css/base/fonts.css: {}
-      css/base/variables.css: {}
-      css/base/base.css: {}
+      css/base/fonts.css: { attributes: { critical: true }, preprocess: false }
+      css/base/variables.css: { attributes: { critical: true }, preprocess: false }
+      css/base/base.css: { attributes: { critical: true }, preprocess: false }
     layout:
-      css/layout/layout.css: {}
-      css/layout/grid.css: {}
+      css/layout/layout.css: { attributes: { critical: true }, preprocess: false }
+      css/layout/grid.css: { attributes: { critical: true }, preprocess: false }
       css/layout/layout-content-narrow.css: {}
       css/layout/layout-content-medium.css: {}
       css/layout/layout-footer.css: {}