sercrod

Shadow DOM bridge

Sercrod can connect a visible shadow template to a host element.

This feature uses the browser's standard Shadow DOM and slot behavior. Sercrod does not reimplement slots, does not move Light DOM children into Shadow DOM, and does not build an internal component renderer.

Sercrod only connects a <template *shadow="'name'"> to an element that has *host.

Because the directive value is a Sercrod expression, fixed connection names should be written as string literals, such as *shadow="'messagebox'" and *host="'messagebox'". The outer double quotes are the HTML attribute quotes. The inner single quotes are the string literal used by the Sercrod expression.

Basic idea

The host element contains the content you want to show. The shadow template defines where that content should appear.

Standard <slot> and slot="..." are handled by the browser. Sercrod only connects the shadow template and the host.

Named slot example

In this example, the host writes the message first and the title second. The shadow template displays the title first and the message second.

Host side

<message-box *host="'messagebox'">
        <p slot="message">Maintenance will be performed on May 20.</p>
        <h2 slot="title">Notice</h2>
</message-box>

Shadow template side

<template *shadow="'messagebox'">
        <section class="message-box">
                <div class="message-box-title">
                        <slot name="title"></slot>
                </div>

                <div class="message-box-message">
                        <slot name="message"></slot>
                </div>
        </section>
</template>

Rendered result, conceptually

<section class="message-box">
        <div class="message-box-title">
                <h2 slot="title">Notice</h2>
        </div>

        <div class="message-box-message">
                <p slot="message">Maintenance will be performed on May 20.</p>
        </div>
</section>

The content is displayed according to the slot positions in the shadow template. slot="title" is displayed at <slot name="title">. slot="message" is displayed at <slot name="message">.

This assignment is standard browser behavior. Sercrod does not process the slot assignment by itself.

Also note that slotted Light DOM children are not physically moved into the Shadow DOM. They are displayed through the standard slot mechanism.

Default slot example

An element without a slot attribute is displayed in the default <slot></slot>.

Host side

<message-box *host="'messagebox'">
        <h2 slot="title">Notice</h2>
        <p>Maintenance will be performed on May 20.</p>
</message-box>

Shadow template side

<template *shadow="'messagebox'">
        <section class="message-box">
                <div class="message-box-title">
                        <slot name="title"></slot>
                </div>

                <div class="message-box-message">
                        <slot></slot>
                </div>
        </section>
</template>

In this example, the title is displayed in the named slot. The paragraph has no slot attribute, so it is displayed in the default slot.

Recommended syntax

The recommended form is to use an explicit connection name.

<template *shadow="'messagebox'">
        ...
</template>

<message-box *host="'messagebox'">
        ...
</message-box>

<template *shadow="'messagebox'"> defines a shadow template named messagebox.

Do not write *shadow="'messagebox'" or *host="'messagebox'" when you mean the fixed name messagebox. The value is evaluated as a Sercrod expression. Write the fixed name as a string literal inside the HTML attribute instead.

<message-box *host="'messagebox'"> connects that shadow template to the host element.

Explicit names make the relationship between the template and the host clear for both humans and AI tools.

CSS scope

Because *shadow and *host use the browser's standard Shadow DOM, they can also use standard Shadow DOM CSS scoping.

Outer page CSS does not normally select elements inside the Shadow DOM with ordinary selectors. CSS written inside the shadow template does not leak out to the outer page.

This is useful for preview components, editor panels, and admin screens where the outer UI CSS and the preview layout CSS should be easier to keep apart.

This separation is not based only on class names or ID names. It comes from the Shadow DOM boundary and the browser's standard CSS scoping behavior.

Example

<style>
        /* Light DOM side CSS */
</style>

<preview-box *host="'previewbox'">
        <div class="same-box" slot="content">
                <h2 class="same-title">Light DOM article title</h2>
                <p class="same-body">Light DOM article body.</p>
        </div>
</preview-box>

<template *shadow="'previewbox'">
        <style>
                /* Shadow DOM side CSS */
        </style>

        <article class="same-box">
                <header class="same-title">Shadow-side title frame</header>

                <main class="same-body">
                        <slot name="content"></slot>
                </main>
        </article>
</template>

In this example, the same class names are used on both sides: .same-box, .same-title, and .same-body.

However, the outer CSS normally targets the Light DOM side. The CSS written inside the shadow template normally targets the Shadow DOM side. Ordinary CSS selectors do not directly cross the Shadow DOM boundary.

Sercrod does not implement CSS isolation by itself. Sercrod connects the shadow template and the host element. CSS scoping is handled by the browser as part of standard Shadow DOM behavior.

Important note about slotted content

Slotted elements are still Light DOM nodes.

Even when they appear at a slot position inside the shadow layout, their actual nodes remain on the Light DOM side. Because of that, slotted elements may still be affected by outer page CSS.

If the preview content itself must be separated from the outer page CSS, render that content inside the Shadow DOM instead of passing it as slotted Light DOM content.

Using Sercrod directives on the Light DOM side

The host side can still be used as a normal Sercrod scope. You can write data, *let, *print, and other Light DOM directives on the host side.

<template *shadow="'profilecard'">
        <section class="profile-card">
                <header>
                        <slot name="name"></slot>
                </header>

                <main>
                        <slot name="body"></slot>
                </main>
        </section>
</template>

<profile-card *host="'profilecard'" data="{ first_name: `Taro`, last_name: `Yamada`, message: `Hello.` }">
        <h2 slot="name" *let="full_name = `${last_name} ${first_name}`" *print="full_name"></h2>
        <p slot="body" *print="message"></p>
</profile-card>

Sercrod processes the Light DOM directives as usual. The processed Light DOM content is then displayed at the slot positions by the browser's standard slot behavior.

What Sercrod does

Sercrod does the following:

What Sercrod does not do

Sercrod does not do the following:

Value-less *host shorthand

A value-less *host is allowed as a shorthand, but it is not recommended.

<template *shadow="'MessageBox'">
        ...
</template>

<message-box *host>
        ...
</message-box>

When *host has no value, Sercrod derives a constructor-style connection name from the host element name.

message-box
        ->
MessageBox

Then Sercrod looks for <template *shadow="'MessageBox'">.

This shorthand is allowed, but explicit names are recommended.

<template *shadow="'messagebox'">...</template>
<message-box *host="'messagebox'">...</message-box>

Explicit names make the connection easier to read, easier to document, and easier for AI tools to understand correctly.

When to use this

This feature is not mainly for printing a single value. For simple value output, data and *print are usually more direct.

<serc-rod data="{ company_name: `Example Company` }">
        <span *print="company_name"></span>
</serc-rod>

*shadow, *host, and standard slots are useful when you want to pass groups of HTML elements into defined positions of a reusable layout.

Good examples include:

Summary

*shadow defines a visible shadow template. *host connects an element to that shadow template.

Sercrod does not reimplement slots. Standard <slot> and slot="..." are handled by the browser.

Sercrod also does not implement CSS isolation by itself. When Shadow DOM is used, CSS scoping is handled by the browser as part of standard Shadow DOM behavior.

Use explicit names whenever possible:

<template *shadow="'messagebox'">...</template>
<message-box *host="'messagebox'">...</message-box>