> For the complete documentation index, see [llms.txt](https://docs.webstudio.is/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.webstudio.is/university/core-components/html-embed.md).

# HTML Embed

Embed custom HTML, CSS, and JavaScript in Webstudio pages.

{% embed url="<https://www.youtube.com/watch?v=ay0_plImm6w>" %}

The HTML Embed component enables the direct integration of custom HTML, CSS, and JavaScript code into your Webstudio project. With this component, you can extend the capabilities of your website, create interactive widgets, integrate external APIs, and implement personalized interactions.

***

## How to use the HTML Embed component

The "HTML Embed" component can be found in Components > General, and you can place it on your canvas by dragging and dropping it or clicking it in the Components panel.

***

## How to add custom code to an HTML Embed instance

You can add your custom HTML, CSS, or JavaScript code to the HTML Embed instance by selecting it and accessing its “Settings”.

The **Code** property is also available in Content mode when the HTML Embed is inside an editable Content Block.

### Code

The "Code" section has a text area for adding your custom code. After you paste your code here, it will be rendered on the canvas. You can add anything to your site including custom widgets, third-party services, API integrations, animations, and interactive content.

### Use assets from your project

When an HTML Embed contains a root-relative URL that matches a unique asset path in your project, Webstudio replaces it with that asset's current URL when rendering the embed. This works for `src` on `<audio>`, `<embed>`, `<img>`, `<input>`, `<script>`, `<source>`, `<track>`, and `<video>`; `srcset` on `<img>` and `<source>`; `href` on `<link>`; `data` on `<object>`; and `poster` on `<video>`. If more than one asset has the same path, Webstudio leaves that URL unchanged.

This applies to those HTML attributes only. It does not rewrite URLs inside script content, such as `fetch("/data.json")`, or CSS, such as `url("/image.png")`.

## Run script on canvas

The "Run Script on Canvas" toggle lets you execute scripts in the canvas preview. It helps you check how an embed behaves, but the preview is not guaranteed to match the published page exactly.

## Client only

If your HTML embed is script-free and only includes items like SVG icons, CSS, or static HTML, you don't need this option.

For embeds with scripts that change HTML, like GSAP animations or sliders, activate the "Client Only" option. This prevents server-side rendering of the HTML. The embed, along with scripts, will render correctly once client-side JavaScript is loaded.

Check out how to embed [GSAP animations](/university/how-tos/how-to-add-a-gsap-animation.md).

<figure><img src="https://330243581-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FTep4EGj6hSC54ozHujyK%2Fuploads%2Fgit-blob-981d6c48deedcd3a58a80830fab871117e8c043a%2Fgsap.png?alt=media&amp;token=5678dff6-3b96-45b9-a659-d4d869321d99" alt="GSAP script configured in an HTML Embed"><figcaption></figcaption></figure>

***

## How to reuse your custom code across multiple web pages

You can reuse your custom code across your project by putting it inside a Slot instance.

1. Add an HTML Embed component to your canvas and set it up with custom code of your choice.
2. Add a [Slot](/university/core-components/slot.md) component to your canvas and place your HTML Embed instance inside it.
3. Now, you can copy and paste this slot instance anywhere on your Webstudio project.

Please note that any updates you make inside your slot will update all other instances of that slot.

## Avoid creating global variables

When using the tag, every variable you create is global by default, which can lead to unpredictable effects.\
\
Example (bad):

```html
<script>
  const a = 1;
</script>
```

In this example, we created a constant `a` and assigned the value 1 to it. However, because script tags by default use global scope, what really happened is that you created `window.a = 1`.\
\
What could go wrong? 😅

1. If you navigate away and come back to the page, the script gets executed again and you will get a syntax error: "Identifier 'a' has already been declared". This is due to the fact that const can be declared only once. You could workaround this by using `var` or `let` instead.
2. If your logic relies on an existing variable and you don't redefine it, it will use any random value that happens to be there at a given time.

### Solution 1 – module

When using the module type, the script has its own scope, and the variables don't become global.

```html
<script type="module">
  const a = 1;
</script>
```

### Solution 2 – function scope

Use an Immediately Invoked Function Expression (IIFE) to create a function scope.

```html
<script>
  (() => {
    const a = 1;
  })();
</script>
```

## Don't use DOMContentLoaded

The **DOMContentLoaded** event won't fire during client-side navigation between pages because, technically, the page isn't reloaded. Use the same logic you intended to write inside that event handler, and if you need to wait for an element to be rendered first, place the embed after it.

## Related

* [Head Slot](/university/core-components/head-slot.md) – Add scripts/styles to document head
* [Content Embed](/university/core-components/content-embed.md) – Render rich text from CMS
* [Element](/university/core-components/element.md) – Semantic HTML elements


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.webstudio.is/university/core-components/html-embed.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
