Skip to content

CSS animation property has differing behaviour when using :global vs :global() #14568

@Jazza-231

Description

@Jazza-231

Describe the bug

Some psuedo code to start us off:
+page.svelte syntax

div.loading
	Load
div

Load.svelte

svg
	path
svg

+page.svelte CSS

.loading {
	:global {
		svg {
			animation: spinner 1s linear infinite
		}
	}
}

@keyframes spinner {
	properly formatted keyframes
}

This +page.svelte CSS does NOT work. The compiled code looks like this:

.loading.svelte-ripfh5 {
	/* :global {*/
		svg {
			animation: spinner 1s linear infinite;
		}
	/*}*/
}

@keyframes svelte-o181q1-spinner {
	0% {
		transform: rotate(0deg);
	}
	100% {
		transform: rotate(360deg);
	}
}

Two things to note:

  1. The :global selector is present but commented out
  2. The spinner animation name is not transformed.

Now if we use :global(svg) {} instead of :global {svg {}}

.loading {
	:global(svg) {
		 animation: spinner 1s linear infinite;
    }
  }

We see that the code compiles properly:

.loading.svelte-o181q1 {
	svg {
		animation: svelte-o181q1-spinner 1s linear infinite;
	}
}

@keyframes svelte-o181q1-spinner {
	0% {
		transform: rotate(0deg);
	}
	100% {
		transform: rotate(360deg);
	}
}

The issue is mitigated by prepending "-global-" to the keyframes definition, as this stops the transforming of "spinner" inside the animation CSS property.

.loading.svelte-6gb5y {
	/* :global {*/
		svg {
			animation: spinner 1s linear infinite;
		}
	/*}*/
}

@keyframes spinner {
	0% {
		transform: rotate(0deg);
		}
	100% {
		transform: rotate(360deg);
	}
}

Ultimately, the issue lies with the keyframes name not being transformed inside of the CSS animation property. Other styles, such as a fill on the child path work fine. This does have fixes, as shown, but the bug is because of the inconsistent behaviour between, what at least has been documented as, identical-results code.

Reproduction

:global {svg {}} : https://svelte.dev/playground/b2fdfc1acdd745019e9d9adc8cc25461?version=5.6.2 - does NOT work
:global {svg {}} with -global-: https://svelte.dev/playground/d1687dba46194588b3c28bb2c463761e?version=5.6.2 - does work
:global(svg) {}: https://svelte.dev/playground/d556d2848000432d9126ad9feeaa204b?version=5.6.2 - does work

In all of these you can see the red fill applies to each perfectly, showing the issue is specific to name transforming.

Logs

No errors as all created CSS is valid

System Info

System:
    OS: Windows 11 10.0.26100
    CPU: (32) x64 13th Gen Intel(R) Core(TM) i9-13900HX
    Memory: 9.99 GB / 31.75 GB
  Binaries:
    Node: 23.3.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.22 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 10.9.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: 9.14.4 - ~\AppData\Local\pnpm\pnpm.CMD
    bun: 1.1.31 - ~\.bun\bin\bun.EXE
  Browsers:
    Edge: Chromium (129.0.2792.79)
    Internet Explorer: 11.0.26100.1882

Those stats are not the full picture
- Windows 11 Pro, 24H2, 26100.2454
- Brave: Version 1.73.97 Chromium: 131.0.6778.108 (Official Build) (64-bit)

Severity

annoyance

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugcssStuff related to Svelte's built-in CSS handling

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions