Lit does not do string concatenation and each html
tag function results in a cached Template element which can be efficiently rendered. This means that each of your html tags get implicitly closed by the browser's HTML parser.
E.g.: html`<table>...`
is parsed by the browser into: html`<table>...</table>`
. From lit.dev documentation on "Well-formed HTML": https://lit.dev/docs/templates/expressions/#well-formed-html
Lit templates must be well-formed HTML. The templates are parsed by the browser's built-in HTML parser before any values are interpolated. Follow these rules for well-formed templates:
Templates should not contain unclosed elements—they will be closed by the HTML parser.
Therefore instead of the following structure:
// Does not work correctly - do not copy this. For demonstration purposes.
const start = html`<table>`;
const content = html`content`;
const end = html`</table>`;
const result = [start, content, end];
return html`${result}`;
// This would render as: <table></table>content<table></table>
Consider the following structure instead where each html tag function is well formed HTML:
const tableFrame = (content) => html`<table>${content}</table>`;
const content = html`content`;
// Pass the content template result into the table frame.
return tableFrame(content);
The following is your code from the playground example restructured in this way:
<script type="module">
import {LitElement, html, css} from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";
class TableExample extends LitElement {
static styles = css`table, th, td { border: 1px solid black; }`;
generateTables() {
const tables = [];
const tableRow1 = html`
<tr>
<td rowspan=2>0</td>
<td>1</td>
</tr>`;
const tableRow2 = html`
</tr>
<td>2</td>
</tr>`;
const table1 = html`
<table>
<tr>
<td rowspan=2>0</td>
<td>1</td>
</tr>
</tr>
<td>2</td>
</tr>
</table>
`;
const tableFrame = (content) => html`<table>${content}</table>`;
// Full table
tables.push(table1);
tables.push(html`<br />`);
// Use tableFrame with custom content.
tables.push(tableFrame(html`<tr><td>Custom Content</td></tr>`));
tables.push(html`<br />`);
// Use tableFrame with the two rows defined earlier.
tables.push(tableFrame([tableRow1, tableRow2]));
return tables;
}
render() {
return this.generateTables();
}
}
customElements.define('table-example', TableExample)
</script>
<table-example></table-example>
As an additional reference the documentation on Templates: https://lit.dev/docs/templates/expressions/#templates