diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php index 8bb9841ae5596..66ad40b3b244e 100644 --- a/apps/theming/lib/Controller/ThemingController.php +++ b/apps/theming/lib/Controller/ThemingController.php @@ -408,11 +408,19 @@ public function getThemeStylesheet(string $themeId, bool $plain = false, bool $w // from the rest of the CSS. $customCssWithoutComments = preg_replace('!/\*.*?\*/!s', '', $customCss); $customCssWithoutComments = preg_replace('!//.*!', '', $customCssWithoutComments); - preg_match_all('/(@[^{]+{(?:[^{}]*|(?R))*})/', $customCssWithoutComments, $atRules); - $atRulesCss = implode('', $atRules[0]); - $scopedCss = preg_replace('/(@[^{]+{(?:[^{}]*|(?R))*})/', '', $customCssWithoutComments); - $css = "$atRulesCss [data-theme-$themeId] { $variables $scopedCss }"; + // Extract @import rules, because they MUST appear at the very top of the final CSS + // If they remain inside the theme scope or behind normal rules, browsers will ignore them + preg_match_all('/(@import[^;]+;)/', $customCssWithoutComments, $imports); + $importsCss = implode('', $imports[0]); + $customCssWithoutImports = preg_replace('/(@import[^;]+;)/', '', $customCssWithoutComments); + + // Extract all remaining @-rules (e.g. @media), because they cannot be nested inside the theme scope + preg_match_all('/(@[^{]+{(?:[^{}]*|(?R))*})/', $customCssWithoutImports, $atRules); + $atRulesCss = implode('', $atRules[0]); + $scopedCss = preg_replace('/(@[^{]+{(?:[^{}]*|(?R))*})/', '', $customCssWithoutImports); + + $css = "$importsCss $atRulesCss [data-theme-$themeId] { $variables $scopedCss }"; } try {