---
description: >-
  This tutorial will guide you through the process of creating custom elements
  using Svelte, building them with Vite, and using them in a standard HTML page.
---

# Creating Custom Elements with Svelte, SvelteKit, and Vite

## Prerequisites

* Node.js and npm installed on your system
* Basic knowledge of Svelte and JavaScript

## Step 1: Set Up the Project

1.  Create a new SvelteKit project:

    ```bash
    npm create svelte@latest my-web-components
    ```

    Choose the options that best suit your needs when prompted.
2.  Navigate to the project directory and install dependencies:

    ```bash
    cd my-web-components
    npm install
    ```

## Step 2: Create a Svelte Component

Create a new file `src/lib/MyComponent.svelte`:

```html
<svelte:options customElement="my-component" />

<script>
  export let name = 'World';
</script>

<h1>Hello {name}!</h1>
```

### **Explanation:**

* The `<svelte:options customElement="my-component" />` tells Svelte to compile this component as a custom element with the tag name `my-component`.
* We define a `name` prop with a default value of 'World'.
* The component renders an `<h1>` element with the greeting.

## Step 3: Create a Custom Elements Export File

Create a new file `src/lib/custom-elements.js`:

```javascript
import MyComponent from './MyComponent.svelte';

export const MyCustomElement = MyComponent.element;
```

**Explanation:**

* We import the Svelte component.
* We export the custom element constructor as `MyCustomElement`. The `.element` property is available on Svelte components when compiled with the `customElement` option.

#### Step 4: Create a Separate Vite Config for Library Build

Create a new file `vite.config.lib.js` in the project root:

```javascript
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

export default defineConfig({
  plugins: [svelte({ compilerOptions: { customElement: true } })],
  build: {
    lib: {
      entry: 'src/lib/custom-elements.js',
      name: 'MyWebComponents',
      fileName: (format) => `my-web-components.${format}.js`
    },
    rollupOptions: {
      output: {
        globals: {
          svelte: 'Svelte'
        }
      }
    }
  }
});
```

**Explanation:**

* We use Vite's library mode to build our custom elements.
* The `entry` point is our `custom-elements.js` file.
* We set the global name to `MyWebComponents`, which will be used to access our custom elements.
* The `fileName` function determines the output file names.

#### Step 5: Update Package.json

Add a new script to your `package.json`:

```json
{
  "scripts": {
    "build:components": "vite build --config vite.config.lib.js"
  }
}
```

This script will use our custom Vite config to build the web components.

#### Step 6: Build the Custom Elements

Run the build command:

```bash
npm run build:components
```

This will generate the compiled JavaScript files in the `dist` directory.

#### Step 7: Use the Custom Elements

Create an HTML file (e.g., `index.html`) to use your custom element:

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Custom Element Demo</title>
</head>
<body>
  <script src="dist/my-web-components.umd.js"></script>
  <script>
    customElements.define('my-component', MyWebComponents.MyCustomElement);
  </script>
  <my-component name="Svelte"></my-component>
</body>
</html>
```

**Explanation:**

* We include the UMD build of our custom elements.
* We define the custom element using `customElements.define()`, associating the tag name with our exported constructor.
* We use the custom element in our HTML, passing the `name` prop.

{% hint style="info" %}
If you want to use the .es.js file, you have to add the type="module"to enable es6 features.

```html
<script src="dist/my-web-components.umd.js"></script>
```
{% endhint %}

#### Step 8: Serve the HTML File

You can use any local server to serve this HTML file. For example, with the `http-server` package:

1.  Install `http-server` globally if you haven't:

    ```bash
    npm install -g http-server
    ```
2.  Navigate to the directory containing your HTML file and run:

    ```bash
    http-server
    ```
3. Open the provided URL in your browser (usually `http://localhost:8080`).

You should now see your custom element rendered on the page!

#### Additional Notes

1. **Browser Support**: Custom elements are supported in all modern browsers, but you might need a polyfill for older browsers.
2. **Styling**: Styles in Svelte components are automatically scoped to the custom element's shadow DOM.
3. **Props**: All exported variables in your Svelte component become properties of the custom element.
4. **Events**: Svelte's event dispatching works with custom elements, allowing you to listen to custom events.
5. **Slots**: You can use Svelte's slot system, which translates to the native slot system of custom elements.

By following this tutorial, you've created a Svelte component, compiled it as a custom element, and used it in a standard HTML page. This approach allows you to leverage Svelte's powerful features while creating reusable web components that can be used in any web project, regardless of the framework.
