CSS
A passthrough tagged template for CSS strings. It has no runtime effect — its sole purpose is to tell editors and language tools that the content is CSS, enabling syntax highlighting, autocompletion, and formatting.
Basic usage
import { const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss } from "ilha";
const const styles: stringstyles = const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss`
button {
background: teal;
color: white;
}
.label {
font-weight: 700;
}
`;
The result is a plain string, identical to what you would get from an untagged template literal.
Using with the builder
Pass the result to the .css() builder method to attach it to an island:
import const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
raw: (value: string) => RawHtml;
mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
... 4 more ...;
onUncaughtError: typeof onUncaughtError;
}
ilha, { const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss } from "ilha";
const const styles: stringstyles = const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss`
.title {
font-size: 1.25rem;
font-weight: 700;
}
button {
background: teal;
color: white;
border: none;
}
`;
const const Card: Island<Record<string, unknown>, Record<never, never>>Card = const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
raw: (value: string) => RawHtml;
mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
... 4 more ...;
onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.css(strings: TemplateStringsArray | string, ...values: (string | number)[]): IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>css(const styles: stringstyles)
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => (
<IntrinsicElements[string]: anydiv>
<IntrinsicElements[string]: anyp class?: string | unknown[] | Record<string, boolean> | undefinedclass="title">Hello</IntrinsicElements[string]: anyp>
<IntrinsicElements[string]: anybutton>Action</IntrinsicElements[string]: anybutton>
</IntrinsicElements[string]: anydiv>
));
Interpolations
Interpolations work as normal string concatenation — values are inserted as-is with no transformation:
import { const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss } from "ilha";
const const accent: "coral"accent = "coral";
const const radius: 4radius = 4;
const const styles: stringstyles = const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss`
button {
background: ${const accent: "coral"accent};
border-radius: ${const radius: 4radius}px;
}
`;
Difference from .css()
css\`and.css()` are intentionally separate:
css`` .css() What it is Named export, tagged template Builder chain method Runtime effect None — returns a plain string Attaches scoped styles to the island Purpose Editor tooling support Actual style attachment
A common pattern is to use both together: author styles with css`` for tooling support, then pass the result to .css() to attach them:
import const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
raw: (value: string) => RawHtml;
mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
... 4 more ...;
onUncaughtError: typeof onUncaughtError;
}
ilha, { const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss } from "ilha";
const const styles: stringstyles = const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss`
p {
color: teal;
}
`; // ← tooling sees CSS here
const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
raw: (value: string) => RawHtml;
mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
... 4 more ...;
onUncaughtError: typeof onUncaughtError;
}
ilha.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.css(strings: TemplateStringsArray | string, ...values: (string | number)[]): IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>css(const styles: stringstyles).IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<never, never>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<never, never>>render(() => <IntrinsicElements[string]: anyp>hello</IntrinsicElements[string]: anyp>); // ← styles are attached here
Organizing styles
For larger islands, keeping styles in a separate variable improves readability and keeps the builder chain focused on structure and behavior:
import const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
raw: (value: string) => RawHtml;
mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
... 4 more ...;
onUncaughtError: typeof onUncaughtError;
}
ilha, { const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss } from "ilha";
const const styles: stringstyles = const css: (strings: TemplateStringsArray | string, ...values: (string | number)[]) => stringcss`
.card {
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 1rem;
}
.card-title {
font-size: 1.125rem;
font-weight: 600;
margin: 0 0 0.5rem;
}
.card-body {
color: #4a5568;
}
button {
margin-top: 1rem;
padding: 0.5rem 1rem;
background: teal;
color: white;
}
`;
const const Card: Island<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>>Card = const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>> & {
html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
raw: (value: string) => RawHtml;
mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
... 4 more ...;
onUncaughtError: typeof onUncaughtError;
}
ilha
.IlhaBuilder<Record<string, unknown>, Record<never, never>, Record<never, never>>.state<boolean, "expanded">(key: "expanded", init?: StateInit<Record<string, unknown>, boolean> | undefined): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>, Record<never, never>>state("expanded", false)
.IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>, Record<never, never>>.on<"button@click">(selectorOrCombined: "button@click", handler: (ctx: HandlerContextFor<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>, "click", Record<never, never>>) => void | Promise<void>): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>, Record<never, never>>on("button@click", ({ state: IslandState<MergeState<Record<never, never>, "expanded", boolean>>state }) =>
state: IslandState<MergeState<Record<never, never>, "expanded", boolean>>state.expanded: MarkedSignalAccessor
(value: boolean) => void (+1 overload)
expanded(!state: IslandState<MergeState<Record<never, never>, "expanded", boolean>>state.expanded: MarkedSignalAccessor
() => boolean (+1 overload)
expanded()),
)
.IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>, Record<never, never>>.css(strings: TemplateStringsArray | string, ...values: (string | number)[]): IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>, Record<never, never>>css(const styles: stringstyles)
.IlhaBuilder<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>, Record<never, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>, Record<never, never>>) => string | RawHtml): Island<Record<string, unknown>, MergeState<Record<never, never>, "expanded", boolean>>render(({ state: IslandState<MergeState<Record<never, never>, "expanded", boolean>>state }) => (
<IntrinsicElements[string]: anydiv class?: string | unknown[] | Record<string, boolean> | undefinedclass="card">
<IntrinsicElements[string]: anyp class?: string | unknown[] | Record<string, boolean> | undefinedclass="card-title">Title</IntrinsicElements[string]: anyp>
{state: IslandState<MergeState<Record<never, never>, "expanded", boolean>>state.expanded: MarkedSignalAccessor
() => boolean (+1 overload)
expanded() ? <IntrinsicElements[string]: anyp class?: string | unknown[] | Record<string, boolean> | undefinedclass="card-body">Content</IntrinsicElements[string]: anyp> : ""}
<IntrinsicElements[string]: anybutton>
{state: IslandState<MergeState<Record<never, never>, "expanded", boolean>>state.expanded: MarkedSignalAccessor
() => boolean (+1 overload)
expanded() ? "Collapse" : "Expand"}
</IntrinsicElements[string]: anybutton>
</IntrinsicElements[string]: anydiv>
));
Notes
- css`` requires editor tooling to provide any benefit. The vscode-styled-components extension and Prettier's
prettier-plugin-styled-components recognize the css tag and apply CSS formatting automatically.
- The tag works with any string content — there is no validation or parsing at runtime. Syntax errors in your CSS will not be caught by ilha itself, only by your editor or browser.