svelte icon indicating copy to clipboard operation
svelte copied to clipboard

Svelte 5 : <tr> is invalid inside <table>

Open mquandalle opened this issue 7 months ago • 13 comments

Describe the bug

The following markup throws an exception

<table><tr></tr></table>
````	

### Reproduction

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE6tWSsvMSS1WsoquVspLzE1VslJyLChQ0lEqqSwAcYrLUnNKUoH84vzSomSQiE1JYlJOqp1NSZGdjT6EAAsA1eTmp2SmZaamKFmVFJWm1sbWAgBDd7JdXgAAAA==

### Logs

_No response_

### System Info

```shell
Svelte 5

Severity

annoyance

mquandalle avatar Dec 05 '23 19:12 mquandalle

The check is happening here.

https://github.com/sveltejs/svelte/blob/cb529fc666a3fb5fd35b27b91c61494a615a8106/packages/svelte/src/compiler/phases/2-analyze/validation.js#L231-L255

It says in the spec that tr is a valid tag, along with td and th. But a tbody should be inserted as a parent tag automatically.
image

So, is svelte trying to enforce the manual addition of tbody?

I can make the PR to allow tr, td and th if that's a valid case.

sidharthv96 avatar Dec 08 '23 06:12 sidharthv96

There is a problem here with hydration. If the SSR generates a table that looks different than the DOM that browser creates via the normalization (e.g. adding a missing tbody), the mismatch can cause the hydration to fail.

The issue was already known, would recommend waiting for maintainer feedback on this.

brunnerh avatar Dec 08 '23 12:12 brunnerh

I don't think Svelte should add the missing tbody here. That would be very confusing to have the framework adding tags not present in the source. Since browsers are accepting a <tr> directly inside a <table> svelte should leave the markup unchanged as does Svelte 4 and other UI frameworks.

mquandalle avatar Dec 08 '23 13:12 mquandalle

This is the result of the limitation of the new way of component rendering - creating all the elements in one go and extracting references to the elements. But when a browser corrects the template structure, it breaks the reference extraction.

Maybe the compiler can just do all the structure correction under the hood. However, it can lead to a confusing experience when a CSS rule doesn't apply to an element or apply to another element because the DOM structure in the source and in the browser differs. So it makes sense to write a markup that will not change its structure.

7nik avatar Jan 09 '24 21:01 7nik

On MDN <tbody> are omitted in some of the examples https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table#simple_table, so I think it is a reasonable way to write the markup for a table, and Svelte rejecting it as invalid is unexpected.

Although if this is an unavoidable technical limitation of the new rendering model that should be explicitly documented, especially in the migration guide.

mquandalle avatar Jan 12 '24 20:01 mquandalle

From @trueadm on an earlier discussion we had about this:

The browser always inserts a <tbody> when you don't put one in. We need to have a <tbody> then to avoid breaking our template mechanic in Svelte 5. There's not a super simple solution here. We either have to try and detect this at runtime or we try and do it statically between modules somehow, but both are pretty difficult. Solid, etc. have the same error. They push for the developer to fix their code and they class this as invalid, as does React.

One possible way would be when we append templates, we can see what the nodes are that we append and check if the parent we're appending to is a <table> and appropriately add a tbody element, and vice versa for when we traverse the elements. This will incur a small overhead cost for checking though, so maybe we can somehow get the compiler to give us a good estimate by looking at the template to see if we're dealing with <tr> elements.

benmccann avatar Jan 19 '24 22:01 benmccann

In my case, <tbody> is there, but <tr> are inside a {#if}{/if} section, the error is raised.

Reproduction

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE31R3UrFMAx-lVIFz0FhTu9mN_A5nBdbl2GxS-eaCofSd7fr_gTl3CXfX9LU815psLx48xybAXjBX8eRP3C6jHNjv0ETxN4aN8kZEVZOaqSqxpo0EJPGIbGS3VpqCE6P55fIRK53KEkZZArlBAMgnc7Mz0xNi-e-ZPksplCjyI5YFK0jik6DUiv5Wfo9IqSxCbUF8yknuRfH4qam1ZCEgj6g6aplqKBprRJREVhiuchi-Qd--h9-_gXHcsmbsW2KoNZ0l1Xhb1S_nSc-NRxxxyLbLeDLNdqyfNdku8gXoC1cdXcG765nZKoP67LrhrFKd4p_O5hO9Qo6XtDkILyHHzQhkBkWAgAA

R3D2 avatar May 03 '24 18:05 R3D2

@R3D2 you forgot about <td>/<th>. You cannot add text right to <tr>.

7nik avatar May 03 '24 19:05 7nik