I am building a custom component (web component) in Svelte and Tailwind.
My goal is to make this component have self-contained styling, but I have trouble with including the Tailwind stylesheet inside my custom component as it is isolated inside a Shadow DOM.
MyComponent.svelte
<svelte:options
customElement={{
tag: "my-component",
}}
/>
<script>
import Child from "./Child.svelte";
</script>
<span class="text-blue-500 p-4">
Foo
<Child />
</span>
Child.svelte
<span class="p-4 text-red-500">Bar</span>
When using <my-component></my-component>
, it is unstyled, as the component is inside the ShadowDOM, it does not have access to the global Tailwind stylesheet.
Is there a way to embed the full Tailwind stylesheet for my component inside the Shadow DOM?
I have had some success with using the svelte preprocessor
svelte.config.js
export default {
preprocess: [preprocess(), vitePreprocess()],
};
and including a link to my tailwind stylesheet in my component
<style lang="postcss" src="./../app.css"></style>
but this is quite cumbersome, as I need to add this line for EVERY child component of MyComponent.svelte
The solution we opted for, was to add a script that imports the css into the Web Components. Inside the html document, we added a <template>
:
<my-component></my-component>
<template id="my-compontent-styling">
<style>
@import url("/assets/app.css")
</style>
</template>
And then in MyComponent.svelte, we inject the css
<svelte:options
customElement={{
tag: "my-component",
}}
/>
<script>
import Child from "./Child.svelte";
function applyStyling(divElement) {
if (!divElement) return;
const template = document.getElementById("my-component-styling");
const node = document.importNode(template.content, true);
divElement.parentNode.appendChild(node);
}
let divElement;
$: applyStyling(divElement);
</script>
<div bind:this={divElement}>
<span class="text-blue-500 p-4">
Foo
<Child />
</span>
</div>