Skip to content

Preserve camelCase for known svg elements #3875

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Madoshakalaka
Copy link
Member

@Madoshakalaka Madoshakalaka commented Jul 16, 2025

Description

This PR fixes SVG filter elements that require camelCase names (like feDropShadow) from being incorrectly lowercased, which causes them to not function at all in browsers.

The Problem

SVG filter effects completely stop working when their element names are lowercased:

<!-- This works in plain HTML -->
<feDropShadow dx="0" dy="0" stdDeviation="10" flood-color="red"/>

<!-- This is what Yew currently generates - DOES NOT WORK -->
<fedropshadow dx="0" dy="0" stddeviation="10" flood-color="red"/>

The browser does not recognize <fedropshadow> as a valid SVG filter primitive, so the entire filter effect is ignored.

The Fix

This PR modifies the tag name handling to:

  • Preserve the original casing for known SVG elements (using the existing is_normalised_element_name function)
  • Continue normalizing regular HTML elements to lowercase

This ensures SVG elements work correctly while maintaining the expected behavior for HTML elements.

Testing

Tested with a minimal reproduction:

  • Before: SVG filters using feDropShadow, feGaussianBlur, etc. do not render
  • After: SVG filters work correctly with preserved casing

Example

html! {
    <svg>
        <defs>
            <filter id="glow">
                <feDropShadow dx="0" dy="0" stdDeviation="10" flood-color="red"/>
            </filter>
        </defs>
        <rect width="100" height="100" filter="url(#glow)" />
    </svg>
}

SVG elements like feDropShadow were incorrectly converted to lowercase,
breaking their functionality. Now properly preserves casing for known
SVG elements while normalizing regular HTML elements.

Fixes svg filter rendering issue where filters would not display.
Copy link

Visit the preview URL for this PR (updated for commit ce06bb1):

https://yew-rs-api--pr3875-fix-svg-filter-casin-4g31o9zo.web.app

(expires Wed, 23 Jul 2025 04:13:33 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Copy link

Benchmark - SSR

Yew Master

Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 310.545 312.538 310.902 0.583
Hello World 10 463.620 515.075 475.294 16.397
Function Router 10 1595.565 1613.881 1601.096 5.824
Concurrent Task 10 1006.353 1008.001 1007.142 0.468
Many Providers 10 1060.612 1099.089 1072.984 12.671

Pull Request

Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 310.511 311.213 310.776 0.197
Hello World 10 463.942 477.993 466.458 4.170
Function Router 10 1623.653 1640.453 1631.533 5.342
Concurrent Task 10 1005.780 1008.112 1007.167 0.613
Many Providers 10 1083.733 1117.613 1095.274 10.370

Copy link

Size Comparison

examples master (KB) pull request (KB) diff (KB) diff (%)
async_clock 99.752 99.752 0 0.000%
boids 168.697 168.697 0 0.000%
communication_child_to_parent 92.070 92.070 0 0.000%
communication_grandchild_with_grandparent 103.230 103.230 0 0.000%
communication_grandparent_to_grandchild 98.220 98.220 0 0.000%
communication_parent_to_child 87.927 87.927 0 0.000%
contexts 104.177 104.177 0 0.000%
counter 84.728 84.728 0 0.000%
counter_functional 85.077 85.077 0 0.000%
dyn_create_destroy_apps 87.655 87.655 0 0.000%
file_upload 98.911 98.911 0 0.000%
function_memory_game 170.503 170.503 0 0.000%
function_router 338.021 338.021 0 0.000%
function_todomvc 163.429 163.429 0 0.000%
futures 236.408 236.408 0 0.000%
game_of_life 104.759 104.759 0 0.000%
immutable 194.198 194.198 0 0.000%
inner_html 80.296 80.296 0 0.000%
js_callback 107.813 107.813 0 0.000%
keyed_list 196.043 196.043 0 0.000%
mount_point 83.604 83.604 0 0.000%
nested_list 112.981 112.981 0 0.000%
node_refs 90.975 90.975 0 0.000%
password_strength 1785.458 1785.458 0 0.000%
portals 92.921 92.921 0 0.000%
router 306.862 306.862 0 0.000%
suspense 111.862 111.862 0 0.000%
timer 88.809 88.809 0 0.000%
timer_functional 94.938 94.938 0 0.000%
todomvc 143.515 143.515 0 0.000%
two_apps 86.017 86.017 0 0.000%
web_worker_fib 135.158 135.158 0 0.000%
web_worker_prime 185.657 185.657 0 0.000%
webgl 83.244 83.244 0 0.000%

✅ None of the examples has changed their size significantly.

@Madoshakalaka Madoshakalaka changed the title Fix SVG filter elements being incorrectly lowercased Automatically use camelCase for known svg elements Jul 16, 2025
@Madoshakalaka
Copy link
Member Author

@WorldSEnder what's your stance on this? I see you worked on #2578 which is related to this issue

@Madoshakalaka Madoshakalaka changed the title Automatically use camelCase for known svg elements Preserve camelCase for known svg elements Jul 16, 2025
@Madoshakalaka
Copy link
Member Author

Related: #3871

Current yew actually panics during hydration while handling these dynamic camelCase svg elements,

It's currently impossible to use these svg elements in a SSR app: lowercase doesn't work, camelCase panics at hydration.

@its-the-shrimp
Copy link
Contributor

Why does Yew even meddle with the element names? shouldn't it pass them to the browser as they're specified?

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.

2 participants