Repository: sveltejs/svelte (JavaScript)

Issue:
Svelte 5: `style:property="value"` doesn’t apply reliably
### Describe the bug

While upgrading my [Sveltia UI](https://github.com/sveltia/sveltia-ui) library to Svelte 5, I’ve noticed that sometimes the `style` property is not applied to elements. The problem happens:

1. when using [`style:property="value"`](https://svelte.dev/docs/element-directives#style-property) but not when using `style="property:value"` or `style:property={value}`
2. when the element is nested
3. when the page is navigated

### Reproduction

1. Clone this repo: https://github.com/kyoshino/svelte-5-style-bug
2. Run `pnpm install && pnpm dev`
3. Open `http://localhost:5173/` in your browser
4. Open the Colors page
5. Notice that the last paragraph is black
6. Reload the page in your browser
7. Notice that the last paragraph is red

### Logs

_No response_

### System Info

```shell
-
```


### Severity

annoyance


Discussion:
I can confirm the bug with latest 244 version.

Also, if you change the colors `page.svelte` this way, it always works:

```svelte
<p style="color:red">Red text</p>
<p style:color="red">Red text</p>

<div>
  <p style="color:red">Red text under nested div</p>
  {#key 1}
    <p style:color="red">Red text under nested div</p>
  {/key}
</div>
```
Is there any chance you could create a REPL version? It will be easier to find what PR was the culprit for the regression this way (you can go to the commit before and load the REPL URL for it and paste in the code to check).
Here we go:

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE02OwYrCMBRFf-XxFKxQ6L6mBT_AnTvjotO8YCBNQvIqSsi_D5mKzPJezrncjNpYStjfMrppIezxHAK2yO9QQ3qSZcIWk1_jXBuR5mgCj9IBmCX4yJDBu4tfHUMBHf0Ch007nKSrmCUGeoXJKVIwwD7xxNToySY6fpDPQNMcYRgh1wr-OxxXOtW2VEN03xPS5Z3RX7RURijzHLcJESDx21I_e-vjIDGSkjheHyYB04shPfxqFfwQRFKiC3-e6LaF3BldpMMWF6-MNqSwr0_KvfwCNb6k-TkBAAA=
Actually with REPL, even this minimal code can reproduce the issue:

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAEyWMQQqDMBBFrzLMuuA-pELv0F3TReuMOBBNyExEEe_eSJfvfd4_cJTIiu514PKZGR0-csYb2p4v0JWjcWNNtQyX8SRrH5ZgPoPaHtkNKaZyD1iYAvbPSRSMNwOdUo0EX4a2-C63ynf_uh3OiWQUJnRWKp_v8wcLKXahiwAAAA==
VERIFIED FIXED with `svelte@5.0.0-next.245` 👍🏼 



Patch:
diff --git a/.changeset/twenty-toes-attack.md b/.changeset/twenty-toes-attack.md
new file mode 100644
index 000000000000..7e445839a700
--- /dev/null
+++ b/.changeset/twenty-toes-attack.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+fix: ensure StyleDirective and ClassDirective are marked as dynamic
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassDirective.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassDirective.js
index f4aaf77589ed..6cea541ea61a 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassDirective.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/ClassDirective.js
@@ -1,10 +1,13 @@
 /** @import { AST } from '#compiler' */
 /** @import { Context } from '../types' */
 
+import { mark_subtree_dynamic } from './shared/fragment.js';
+
 /**
  * @param {AST.ClassDirective} node
  * @param {Context} context
  */
 export function ClassDirective(node, context) {
+	mark_subtree_dynamic(context.path);
 	context.next({ ...context.state, expression: node.metadata.expression });
 }
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/StyleDirective.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/StyleDirective.js
index 8910d9eae074..7d6eb5be99e8 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/StyleDirective.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/StyleDirective.js
@@ -13,6 +13,8 @@ export function StyleDirective(node, context) {
 		e.style_directive_invalid_modifier(node);
 	}
 
+	mark_subtree_dynamic(context.path);
+
 	if (node.value === true) {
 		// get the binding for node.name and change the binding to state
 		let binding = context.state.scope.get(node.name);
@@ -22,8 +24,6 @@ export function StyleDirective(node, context) {
 				node.metadata.expression.has_state = true;
 			}
 		}
-
-		mark_subtree_dynamic(context.path);
 	} else {
 		context.next();
 


Test patch:
diff --git a/packages/svelte/tests/runtime-runes/samples/directives/_config.js b/packages/svelte/tests/runtime-runes/samples/directives/_config.js
new file mode 100644
index 000000000000..afe87e184dfc
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/directives/_config.js
@@ -0,0 +1,12 @@
+import { test } from '../../test';
+
+export default test({
+	html: `<div><p class="foo" style="color: red;">This text should be red with a class of foo</p></div>`,
+
+	async test({ assert, target }) {
+		const p = target.querySelector('p');
+
+		assert.equal(p?.className, `foo`);
+		assert.equal(p?.style.color, `red`);
+	}
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/directives/main.svelte b/packages/svelte/tests/runtime-runes/samples/directives/main.svelte
new file mode 100644
index 000000000000..96c7fed74f39
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/directives/main.svelte
@@ -0,0 +1,3 @@
+<div>
+	<p style:color="red" class:foo={true}>This text should be red with a class of foo</p>
+</div>