---
title: 'PortalRoot'
description: 'PortalRoot is a React component that helps you make React Portals.'
version: 0.0.0-development
generatedAt: 2026-06-12T14:12:20.478Z
checksum: 9e4431df834c9b59cac82d30a49e56b95a0858679657373ee1a87dc1a6590110
---

# PortalRoot

## Import

```tsx
import { PortalRoot } from '@dnb/eufemia'
```

## Description

`PortalRoot` is a React component that helps you make React's [createPortal](https://react.dev/reference/react-dom/createPortal).

It lets you render some children into a different part of the DOM.

### Good to know

- It contains CSS styles and screen reader accessibility features needed for proper usage of portals.
- It comes with support for [style isolation](/uilib/usage/customisation/styling/style-isolation/).
- Everything inside the `PortalRoot` can later be customized and stacked on top of each other using CSS `z-index`.
- It is used in other components, like [Tooltip](/uilib/components/tooltip), [Modal](/uilib/components/modal), [TermDefinition](/uilib/components/term-definition) and [DatePicker's calendar](/uilib/components/date-picker).
- A wrapper is inserted automatically as a child node to the HTML `<body>` or the `<IsolatedStyleScope scopeHash="your-scope" />` element.
- It adds `dnb-core-style` class to the portal element, so you do not need to deal with that yourself.
- In order to remove it from the accessibility tree, it uses `role="presentation"`. That means, when your content is visible, you need to set focus to it, so screen readers can read it.
- `PortalRoot` props override values from `PortalRoot.Provider` if both are present.
- `beforeSelector` takes precedence over `insideSelector` when both are provided on the same level.

## Relevant links

- [Source code](https://github.com/dnbexperience/eufemia/tree/main/packages/dnb-eufemia/src/components/portal-root)
- [Docs code](https://github.com/dnbexperience/eufemia/tree/main/packages/dnb-design-system-portal/src/docs/uilib/components/portal-root)

## Usage

For basic usage, just wrap your content with the `PortalRoot` component:

```tsx
import { PortalRoot } from '@dnb/eufemia'

render(<PortalRoot>Your content</PortalRoot>)
```

It will create a wrapper div and insert it as a child node to the HTML `<body>` element:

```html
<body>
  <!-- The portal root will be inserted here -->
  <!-- Other content -->
</body>
```

## Define where the portal root should be rendered

Sometimes you might want to have more control over where the portal root element is placed in the HTML structure.

To achieve this, you can create an element in your HTML with the id `eufemia-portal-root`:

```html
<body>
  <div class="with-something-else">
    <div id="app" />
    <div id="eufemia-portal-root" />
  </div>
</body>
```

### Customize with id property

You can also customize the portal root element by passing a custom `id` property to the `PortalRoot` component:

```tsx
import { PortalRoot } from '@dnb/eufemia'

// This will use the existing element with id="my-custom-portal-root"
render(<PortalRoot id="my-custom-portal-root">Your content</PortalRoot>)
```

This will create or reuse an element with the specified id in the HTML structure:

```html
<body>
  <div class="with-something-else">
    <div id="app" />
    <div id="my-custom-portal-root" />
  </div>
</body>
```

### Without pre-existing element

If you are not able to modify the HTML structure, you can make use of the `beforeSelector` or `insideSelector` property to define where the portal root should be placed.

You can pass these selectors directly to `PortalRoot`:

```tsx
import { PortalRoot } from '@dnb/eufemia'

// Insert the portal root before the element with id="my-custom-id"
render(
  <PortalRoot beforeSelector="#my-custom-id">Your content</PortalRoot>
)

// Insert the portal root as the first child inside the element with class="my-selector"
render(<PortalRoot insideSelector=".my-selector">Your content</PortalRoot>)
```

### Customize properties via provider (context)

You can also pass properties to each `PortalRoot` by using the `PortalRoot.Provider`.

In this example, the `DatePicker` component renders its portal content before the element with the id `my-custom-id`.

```tsx
import { PortalRoot, DatePicker } from '@dnb/eufemia'

render(
  <PortalRoot.Provider beforeSelector="#my-custom-id">
    <DatePicker />
  </PortalRoot.Provider>
)
```

This makes the `DatePicker` render its portal content right before `my-custom-id`.

```html
<body>
  <div class="with-something-else">
    <!-- The portal root will be inserted here -->
    <div id="my-custom-id" />
  </div>
</body>
```

### Forward HTML attributes to portal content

`PortalRoot.Provider` also forwards any extra HTML attributes to the portal DOM element. Any standard HTML attribute you pass will be applied to every portal element rendered by components inside the provider (such as Dropdown, Autocomplete, DatePicker, Dialog, Drawer, Popover, and Tooltip).

```tsx
import { PortalRoot, Dropdown, Dialog } from '@dnb/eufemia'

render(
  <PortalRoot.Provider data-my-need="something">
    <Dropdown />
    <Dialog />
  </PortalRoot.Provider>
)
```

In this example, every portal element will receive `data-my-need="something"` for content rendered outside the main React tree.

### BrowserTranslate helper (Google Translate)

The `BrowserTranslate` helper component prevents browser translation tools (such as Google Translate) from modifying the content of form components. It works by combining the Eufemia Provider's `formElement` context with `PortalRoot.Provider`, so both the visible component (e.g. a button) and its portal-rendered content (e.g. a dropdown list) receive `translate="no"`.

```tsx
import { BrowserTranslate } from '@dnb/eufemia/shared'
import { Dropdown } from '@dnb/eufemia'

render(
  <BrowserTranslate off>
    <Dropdown data={['Brukskonto', 'Sparekonto', 'BSU']} />
  </BrowserTranslate>
)
```

When `off` is set, every form component inside the scope will have `translate="no"` on both its trigger element and its portal content. Without `off`, the component renders children as-is.

## Properties


```json
{
  "props": {
    "ref": {
      "doc": "The ref of the element that will be used.",
      "type": [
        "React.Ref<HTMLElement>",
        "React.RefObject<HTMLElement>"
      ],
      "status": "optional"
    },
    "id": {
      "doc": "The id used for the portal root element. Defaults to `eufemia-portal-root`. If an element with this id already exists in the DOM, it will be reused.",
      "type": "string",
      "status": "optional"
    },
    "insideSelector": {
      "doc": "CSS selector for a container to place the portal root inside. The portal element is inserted as the first child of the matched element.",
      "type": "string",
      "status": "optional"
    },
    "beforeSelector": {
      "doc": "CSS selector for a target element; the portal root will be inserted directly before the first matched element.",
      "type": "string",
      "status": "optional"
    },
    "children": {
      "doc": "The content that will be placed in a React Portal.",
      "type": "React.ReactNode",
      "status": "required"
    },
    "[HTML attributes]": {
      "doc": "When used on `PortalRoot.Provider`, any extra HTML attributes (e.g. `translate`, `lang`, `dir`, `data-*`) are forwarded to the portal DOM element. Props on `PortalRoot` itself take precedence.",
      "type": "various",
      "status": "optional"
    }
  }
}
```
