Skip to content

fix: strip trailing semicolons in style directive reactive updates#18200

Open
OfirHaf wants to merge 4 commits into
sveltejs:mainfrom
OfirHaf:fix/style-directive-trailing-semicolon
Open

fix: strip trailing semicolons in style directive reactive updates#18200
OfirHaf wants to merge 4 commits into
sveltejs:mainfrom
OfirHaf:fix/style-directive-trailing-semicolon

Conversation

@OfirHaf

@OfirHaf OfirHaf commented May 10, 2026

Copy link
Copy Markdown
Contributor

What's happening

When a style: directive value contains a trailing semicolon, initial render and reactive updates behave differently:

  • Initial render — Svelte sets dom.style.cssText, which is lenient and accepts trailing semicolons (the browser strips them).
  • Reactive update — Svelte calls dom.style.setProperty(key, value), which silently rejects values containing semicolons. The style never updates.

Reproduction from #18182:

<script>
  let angle = $state(250);
  let style = $derived(`conic-gradient(red ${angle}deg, blue 0);`);
</script>

<div style:background={style}>Test</div>
<button onclick={() => angle = 50}>Update</button>

Click the button — background never changes because setProperty drops the value.

Fix

In update_styles, strip trailing semicolons from the value before passing it to setProperty, so both paths handle the input consistently.

var str_value = String(value).replace(/;+\s*$/, '');
dom.style.setProperty(key, str_value, priority);

This is intentionally narrow — only trailing semicolons are removed, which is what the browser would strip anyway. Semicolons inside the value (e.g. in url("data:...")) are not affected.

Note: #18173 handles the related SSR/security case for structural semicolons in the to_style path. This PR covers the client-side reactive update path in update_styles.

Closes #18182

…Property

When a reactive style directive value contains a trailing semicolon (e.g.
`style:background={`conic-gradient(...);'`}`), the initial render works
because it goes through cssText which tolerates semicolons, but subsequent
reactive updates call el.style.setProperty() which silently rejects values
containing semicolons, leaving the style unchanged.

Strip trailing semicolons from the value in update_styles before calling
setProperty, making reactive updates consistent with the initial render.

Fixes sveltejs#18182
@changeset-bot

changeset-bot Bot commented May 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e86e2c7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@@ -15,7 +15,10 @@ function update_styles(dom, prev = {}, next, priority) {
if (next[key] == null) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small readability nit: since value is already assigned from next[key], this can use the local variable consistently.

Suggested change
if (next[key] == null) {
if (value == null) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this PR requires a changeset.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, applied the suggestion — changed to if (value == null).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the changeset in .changeset/cuddly-cougars-grow.md with a patch bump.

Applies reviewer suggestion for consistency since value is already
assigned from next[key] on the line above.

Also adds required changeset for patch version bump.
@RazinShafayet2007

Copy link
Copy Markdown
Contributor

Would you mind adding a small regression test? The location is probably under packages/svelte/tests/runtime-browser/samples/.

@OfirHaf

OfirHaf commented May 10, 2026

Copy link
Copy Markdown
Contributor Author

Added a regression test under packages/svelte/tests/runtime-browser/samples/style-directive-trailing-semicolon/. It covers the initial render with a trailing semicolon, a reactive update with a new value that also has a trailing semicolon, and an update to a clean value without one.

@7nik

7nik commented May 10, 2026

Copy link
Copy Markdown
Contributor

I kind of dislike doing the replacement for setting, strictly speaking, invalid value. So maybe a better way would be just logging a dev-only warning about ; in the value, or maybe even checking that the value wasn't rejected.

@OfirHaf

OfirHaf commented May 11, 2026

Copy link
Copy Markdown
Contributor Author

That's a fair point — silently stripping the value isn't ideal. Would it work to keep the strip but add a DEV guard warning alongside it? The value with a trailing semicolon is technically invalid so the strip keeps prod CSS correct, but in dev mode the user would get an explicit console warning that the style directive value shouldn't end with ;. If you'd prefer to skip the strip entirely and only warn (and let the browser handle the invalid value), I can go that direction too — just let me know what works better for the codebase.

@OfirHaf

OfirHaf commented May 15, 2026

Copy link
Copy Markdown
Contributor Author

Good point @7nik — just pushed an update that adds a DEV-only console.warn when the value has a trailing semicolon, so the developer gets an explicit signal to fix the value rather than it being silently cleaned up. The strip is still in place in both dev and prod since setProperty rejects values with trailing semicolons outright, but now in dev the warning makes the invalid value visible. Happy to drop the strip entirely and only warn if you'd prefer to let the browser handle rejection — just let me know which direction fits better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

style:property directive behavior inconsistent with invalid CSS values on updates

3 participants