https://github.com/tkdeng/embed-portal
A reimplementation of what the protal element could have been.
https://github.com/tkdeng/embed-portal
css embed-portal html html-css-javascript html-element html-embed html-embed-portal html-portal html5 iframe javascript js shadow-dom
Last synced: 7 days ago
JSON representation
A reimplementation of what the protal element could have been.
- Host: GitHub
- URL: https://github.com/tkdeng/embed-portal
- Owner: tkdeng
- License: mit
- Created: 2026-05-26T00:29:20.000Z (18 days ago)
- Default Branch: main
- Last Pushed: 2026-05-26T00:53:45.000Z (18 days ago)
- Last Synced: 2026-06-01T04:33:11.876Z (12 days ago)
- Topics: css, embed-portal, html, html-css-javascript, html-element, html-embed, html-embed-portal, html-portal, html5, iframe, javascript, js, shadow-dom
- Language: JavaScript
- Homepage:
- Size: 3.91 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: LICENSE
Awesome Lists containing this project
README
# Embed Portal
Embed Portal is a lightweight custom element that allows you to fetch external HTML and inject it directly into a Shadow DOM.
While it functions similarly to an ``, using a Shadow DOM keeps the embedded content encapsulated within the light DOM's styling and structure without the overhead or isolation constraints of a full iframe.
## Why Use It?
- Encapsulation: Styles defined in the parent document won't leak into the portal (and vice versa).
- Performance: Avoids the heavy resource usage associated with loading multiple independent browser contexts (iframes).
- Seamless Integration: Allows you to fetch and display modular components or partial pages dynamically.
## Installation
Add this script to your project:
```html
```
## Usage
Simply use the `` tag in your HTML:
```html
```
### Handling Events
You can react to the portal's lifecycle using standard event listeners:
```js
const portal = document.querySelector('embed-portal');
// Handle successful load
portal.addEventListener('load', (event) => {
console.log('Portal content injected successfully!');
// Access the shadow root directly from the event
const shadowRoot = event.detail.root;
});
// Handle errors
portal.addEventListener('error', (event) => {
console.error('Failed to load portal:', event.detail.message);
});
```
## Attributes
| Attribute | Description |
| --------- | ----------- |
| src | The URL of the HTML content to embed (must be same-origin). |
| noscript | Optional. If present, prevents the script from attempting to extract and execute `` tags from the fetched content. |
| onload | Optional. A string containing JavaScript to execute once the content has been successfully injected. |
## How It Works
1. Polling: The script periodically scans the DOM for new `<embed-portal>` elements.
2. Fetching: It performs a GET request to the provided src with a custom X-Fetch-Dest: embed-portal header.
3. Parsing: It extracts `<link>` stylesheets and `<style>` blocks from the document head and injects them into the Shadow DOM to preserve styling.
4. Injection: It extracts the `<body>` content and appends it into the shadow root.
5. Events: Once loaded, it dispatches a custom `load` event containing the `shadow` root in the `detail` object (or `error` if the request fails).
## Technical Notes
- Security: This implementation enforces same-origin requests to prevent CORS issues. Invalid requests trigger an `error` event and log a sanitized URL to the console.
- Script Handling: By default, it attempts to extract and register scripts from the fetched page to the main document head. You can disable this with the `noscript` attribute.