diff --git a/core/lib/Drupal/Core/Asset/AssetResolver.php b/core/lib/Drupal/Core/Asset/AssetResolver.php
index 6f477d19f6..5f6d7d8b54 100644
--- a/core/lib/Drupal/Core/Asset/AssetResolver.php
+++ b/core/lib/Drupal/Core/Asset/AssetResolver.php
@@ -106,6 +106,18 @@ protected function getLibrariesToLoad(AttachedAssetsInterface $assets) {
     );
   }
 
+  protected function componentDefinition($name, &$definition) {
+    if (str_starts_with($name, 'TWIG_ATTACH---')) {
+      [, $file_type, $file_to_attach] = explode('>>', $name);
+      $file_to_attach = str_replace('|', '/', $file_to_attach);
+      $definition = [
+        $file_type => [
+          ['data' => $file_to_attach],
+        ],
+      ];
+    }
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -131,6 +143,7 @@ public function getCssAssets(AttachedAssetsInterface $assets, $optimize) {
     foreach ($libraries_to_load as $library) {
       [$extension, $name] = explode('/', $library, 2);
       $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
+      $this->componentDefinition($name, $definition);
       if (isset($definition['css'])) {
         foreach ($definition['css'] as $options) {
           $options += $default_options;
diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index 71f587630c..20c9231b93 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -108,6 +108,7 @@ public function getFunctions() {
       new TwigFunction('active_theme_path', [$this, 'getActiveThemePath']),
       new TwigFunction('active_theme', [$this, 'getActiveTheme']),
       new TwigFunction('create_attribute', [$this, 'createAttribute']),
+      new TwigFunction('add_css', [$this, 'addCss'], ['needs_context' => TRUE]),
     ];
   }
 
@@ -363,6 +364,18 @@ public function attachLibrary($library) {
     $this->renderer->render($template_attached);
   }
 
+  public function addCss($context, array $css) {
+    $active_theme = $this->getActiveTheme();
+    $theme_hook = $context['theme_hook_suggestions'][0] ?? $context['theme_hook_original'];
+    foreach ($css as $css_file) {
+      $slash_pipe = str_replace('/', '|', $css_file);
+      // This is a temporary library with a crazy name that is later parsed to
+      // add the asset.
+      $theme_library_name = "$active_theme/TWIG_ATTACH---component--$theme_hook>>css>>$slash_pipe";
+      $this->attachLibrary($theme_library_name);
+    }
+  }
+
   /**
    * Provides a placeholder wrapper around ::escapeFilter.
    *
