---
metadata:
  - name: generator
    content: Diplodoc Platform v5.70.0
alternate:
  - https://divkit.tech/docs/en/quickstart/web.md
  - https://divkit.tech/docs/ru/quickstart/web.md
  - href: https://divkit.tech/docs/en/quickstart/web.md
    type: text/markdown
    title: Markdown version
  - href: https://divkit.tech/docs/en/llms.txt?revision=r22102947
    rel: describedby
---
> **Documentation Index:** Fetch the complete configuration index at https://divkit.tech/docs/en/llms.txt?revision=r22102947

# Instructions for Web

DivKit for Web is the `@divkitframework/divkit` npm package. It renders a JSON layout into a DOM element in the browser or into an HTML string on the server. To see what a layout looks like without integrating the library into your project, use [DivKit Web Playground](https://divkit.tech/docs/en/concepts/playground.md#web).

## Connecting the library and rendering the first card {#setup}

### Installing the package {#install}

Install the package from npm:

```bash translate=no
npm i @divkitframework/divkit --save
```

The package contains several modules, each exporting a `render` function. Choose a module depending on where the layout is rendered:

| Module | Purpose |
| --- | --- |
| `@divkitframework/divkit/client` | Rendering in the browser only. |
| `@divkitframework/divkit/client-hydratable` | Rendering in the browser with hydration of the HTML received from the server. This module is slightly larger than `client`. |
| `@divkitframework/divkit/server` | Rendering into an HTML string on the server. |

The modules ship as both ES modules and CommonJS: Node.js and bundlers pick the appropriate format themselves. TypeScript type definitions are included in the package.

### Including the styles {#css}

Every way of using the library requires the `dist/client.css` style file. You can include it in any way. For example, import the file as a module if your bundler handles CSS:

```js translate=no
import '@divkitframework/divkit/dist/client.css';
```

Or link the file in the HTML page:

```html translate=no
<link rel="stylesheet" href="node_modules/@divkitframework/divkit/dist/client.css">
```

### Rendering on the client {#client-render}

Add an element to the page that the card will be rendered into:

```html translate=no
<div id="root"></div>
```

Call the `render` function from the `client` module. Pass it the block identifier, the target element, and the JSON layout. As an example, let's output a short piece of text to the screen:

```js translate=no
import { render } from '@divkitframework/divkit/client';
import '@divkitframework/divkit/dist/client.css';

const json = {
    card: {
        log_id: 'text',
        states: [
            {
                state_id: 0,
                div: {
                    type: 'text',
                    text: 'Hello, DivKit!'
                }
            }
        ]
    }
};

const instance = render({
    id: 'hello',
    target: document.querySelector('#root'),
    json,
    onError(details) {
        console.error(details.error);
    }
});
```

If everything is set up correctly, the page displays the text "Hello, DivKit!". The function returns a card instance that you can use to [update or destroy the card](#instance).

### Server-side rendering and hydration {#ssr}

On the server, use the `server` module. Its `render` function doesn't accept the `target` parameter and returns an HTML string:

```js translate=no
import { render } from '@divkitframework/divkit/server';

const html = render({
    id: 'hello',
    json,
    onError(details) {
        console.error(details.error);
    }
});
```

Insert the resulting string into the container element and include the `dist/client.css` file in the page. To make the card interactive, call `render` from the `client-hydratable` module in the browser with the `hydrate: true` parameter:

```js translate=no
import { render } from '@divkitframework/divkit/client-hydratable';

render({
    id: 'hello',
    target: document.querySelector('#root'),
    hydrate: true,
    json,
    onError(details) {
        console.error(details.error);
    }
});
```

{% note info %}

Pass the same `id` and `json` on the server and on the client. The `id` value is used to generate identifiers and classes in the markup.

{% endnote %}

A ready-made example of server-side rendering with hydration is available on [GitHub](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/ssr).

### Using the library without a build {#no-build}

You can use the library in the browser without a bundler, but a build is recommended for production projects.

{% list tabs %}

- ES modules

  Import the `render` function from the `dist/esm/client.mjs` file:

  ```html translate=no
  <link rel="stylesheet" href="./node_modules/@divkitframework/divkit/dist/client.css">

  <div id="root"></div>

  
  ```

- Global variable

  The `dist/browser/client.js` script adds the `render` function to the `window.Ya.DivKit` global object:

  ```html translate=no
  <link rel="stylesheet" href="./node_modules/@divkitframework/divkit/dist/client.css">

  <div id="root"></div>

  
  
  ```

  The `Ya.Divkit` spelling is deprecated: use `Ya.DivKit`.

{% endlist %}

### React {#react}

For React, there is a separate package: [@divkitframework/react](https://github.com/divkit/divkit/tree/main/client/web/divkit-react). Its `DivKit` component accepts the `render` function parameters as props.

## Parameters of the render function {#render-params}

The `id` and `json` parameters are required in all modules, and the `target` parameter is required in the `client` and `client-hydratable` modules. All other parameters are optional. The table lists the main parameters; for the full list with descriptions, see the [package README](https://github.com/divkit/divkit/tree/main/client/web/divkit).

| Parameter | Modules | Description |
| --- | --- | --- |
| `id` | All | **string**. Unique block identifier. It is used to generate identifiers and classes, so a page must not contain two blocks with the same `id`. |
| `json` | All | **object**. JSON layout: the `card` object and the optional `templates` object. |
| `target` | `client`, `client-hydratable` | **HTMLElement**. The element that the card is rendered into. |
| `hydrate` | `client-hydratable` | **boolean**. Set to `true` to hydrate the HTML that is already inside `target`. |
| `onError` | All | **function**. Handler for errors and warnings. See [Errors](#errors). |
| `onStat` | `client`, `client-hydratable` | **function**. Handler for logging clicks and impressions. See [Statistics](#stat). |
| `onCustomAction` | `client`, `client-hydratable` | **function**. Handler for actions that DivKit doesn't execute itself. See [Custom actions](#custom-actions). |
| `builtinProtocols` | All | **string[]**. Default value: `['http', 'https', 'tel', 'mailto', 'intent']`. Elements with an action whose protocol is in the list are rendered as `<a>` links, and the browser handles clicks on them. |
| `platform` | All | **string**. Possible values: `desktop`, `touch`, `auto`. Default value: `auto`. Tunes the handling of mouse or touch events. |
| `direction` | All | **string**. Possible values: `ltr`, `rtl`. Default value: `ltr`. Direction of the text and layout. |
| `theme` | All | **string**. Possible values: `system`, `light`, `dark`. Default value: `system`. See [Theming](#theming). |
| `themeVariableName` | All | **string**. Name of the variable that stores the current theme. See [Theming](#theming). |
| `globalVariablesController` | `client`, `client-hydratable` | **object**. Controller of global variables. See [Variables](#variables). |
| `typefaceProvider` | All | **function**. Returns the value of the `font-family` CSS property for a font from the layout. See [Fonts](#fonts). |
| `customComponents` | All | **Map**. Descriptions of custom components. See [Custom components](#custom-components). |
| `extensions` | `client`, `client-hydratable` | **Map**. Extensions that the layout enables by identifier. See [Extensions](#extensions). |
| `extensionsForAllComponents` | `client`, `client-hydratable` | **array**. Extensions that are applied to every element. See [Extensions](#extensions). |
| `fetchInit` | `client`, `client-hydratable` | **object** or **function**. The second argument of the `fetch` function for requests sent by the `download` and `submit` actions. |
| `tooltipRoot` | `client`, `client-hydratable` | **HTMLElement**. The element that tooltips and menus are attached to instead of `target`. Helps avoid clipping. |
| `store` | All | **object**. External storage for [stored values](../concepts/stored-values.md). The storage implements the `get` and `set` methods; the `get` method must be synchronous. |
| `videoPlayerProvider` | All | **object**. A provider of your own video player. On the server, it contains the `template` property, a string or a function that returns the player markup; on the client, it contains the `instance` function that creates a player instance. |
| `mix` | All | **string**. Additional CSS class of the root element. |
| `customization` | All | **object**. CSS classes for the scroll buttons of `gallery` and `pager` on desktop, as well as for the popup menu and its items. |

## Handling actions, statistics, and errors {#callbacks}

### Custom actions {#custom-actions}

To make the interface interactive, add [action](https://divkit.tech/docs/en/concepts/interaction.md) handling. DivKit executes actions with the `div-action` protocol itself, and the browser opens links with protocols from the `builtinProtocols` list. All other actions are passed to the `onCustomAction` handler: these are links with other protocols and actions with `"typed": {"type": "custom"}`.

As an example, let's turn the text into a button that shows a notification when clicked. Add an action to the element:

```json translate=no
"actions": [
    {
        "log_id": "button_pressed",
        "url": "notification://show-toast?text=Hello%2C%20DivKit%21"
    }
]
```

Handle this action in `onCustomAction`:

```js translate=no
render({
    id: 'hello',
    target: document.querySelector('#root'),
    json,
    onCustomAction(action) {
        const [address, query = ''] = (action.url || '').split('?');

        if (address === 'notification://show-toast') {
            alert(new URLSearchParams(query).get('text'));
        }
    }
});
```

This way, the JSON layout can affect not only the state of the card itself but the entire application. The data of an action with `"typed": {"type": "custom"}` is passed in the `action.payload` field. For more information, see [Custom actions](https://divkit.tech/docs/en/concepts/interaction.md#custom-actions).

### Statistics {#stat}

The `onStat` handler is intended for logging clicks and impressions. The `details.action` field contains the action, and the `details.type` field takes one of the following values:

- `click`: A click on an element with an action, as well as any action that has no type of its own.
- `visible`: An element with `visibility_actions` became visible.
- `disappear`: An element with `disappear_actions` disappeared.
- `trigger`: A [trigger](https://divkit.tech/docs/en/concepts/triggers.md) fired.

```js translate=no
render({
    id: 'hello',
    target: document.querySelector('#root'),
    json,
    onStat(details) {
        console.log(details.type, details.action.log_id);
    }
});
```

### Errors {#errors}

The `onError` handler receives errors and warnings that occur while the layout is parsed and rendered. The `details.error` object has a `level` field with the `error` or `warn` value and an optional `additional` field with extra data. If the handler isn't set, DivKit writes the messages to the console.

```js translate=no
render({
    id: 'hello',
    target: document.querySelector('#root'),
    json,
    onError(details) {
        const { level, message, additional } = details.error;

        console.log(level, message, additional);
    }
});
```

## Theming {#theming}

The `theme` parameter sets the card theme: `light`, `dark`, or `system`. With the `system` value, which is the default, the theme follows the user's system settings (the `prefers-color-scheme` media query) and changes together with them. System settings aren't available on the server, so with the `system` value the layout is rendered there in the light theme.

To use the current theme in the layout, specify a variable name in the `themeVariableName` parameter. DivKit creates a string variable with this name and keeps the `light` or `dark` value in it. Use the variable in [expressions](https://divkit.tech/docs/en/concepts/expressions.md): when the theme changes, the properties that depend on it are updated without reloading the page.

{% note info %}

If the `themeVariableName` parameter isn't passed, the variable isn't created. The variable name must not match the names of card variables or global variables; otherwise, DivKit reports the `Duplicate variable` error.

{% endnote %}

```js translate=no
render({
    id: 'themed',
    target: document.querySelector('#root'),
    json,
    theme: 'system',
    themeVariableName: 'theme'
});
```

{% cut "View layout example" %}

```json translate=no
{
    "card": {
        "log_id": "themed_card",
        "states": [
            {
                "state_id": 0,
                "div": {
                    "type": "text",
                    "text": "Hello, DivKit!",
                    "text_color": "@{theme == 'dark' ? '#ffffff' : '#000000'}",
                    "background": [
                        {
                            "type": "solid",
                            "color": "@{theme == 'dark' ? '#000000' : '#ffffff'}"
                        }
                    ]
                }
            }
        ]
    }
}
```

{% endcut %}

The `setTheme` instance method changes the theme of a card that is already rendered, for example `instance.setTheme('dark')`. The package type definitions mark this method as deprecated.

## Variables {#variables}

The `client` and `client-hydratable` modules export functions for working with [global variables](https://divkit.tech/docs/en/concepts/variables.md#global). The `createVariable` function creates a variable, and `createGlobalVariablesController` creates a controller that makes variables available in the card. To share variables between several cards, pass the same controller to each `render` call.

```js translate=no
import {
    render,
    createVariable,
    createGlobalVariablesController
} from '@divkitframework/divkit/client';

const userName = createVariable('user_name', 'string', 'Guest');

const controller = createGlobalVariablesController();
controller.setVariable(userName);

render({
    id: 'hello',
    target: document.querySelector('#root'),
    json,
    globalVariablesController: controller
});

const unsubscribe = userName.subscribe(value => {
    console.log(value);
});

userName.setValue('Alice');
```

In the layout, the variable is available by its name, for example `@{user_name}`. Variable methods:

- `subscribe`: Calls the handler with the current value and then on every change. Returns a function that cancels the subscription.
- `setValue`: Sets a new value.
- `getValue`: Returns the current value.

Variable names within one controller must be unique: the `setVariable` method throws an exception when you add a second variable with the same name.

## Extending the functionality {#extending}

### Custom components {#custom-components}

The [custom](https://divkit.tech/docs/en/concepts/divs/2/div-custom.md) element is rendered using HTML custom elements. In the `customComponents` parameter, pass a `Map` where the key is the `custom_type` value from the layout and the value is a component description with the tag name in the `element` field:

```js translate=no
import { render } from '@divkitframework/divkit/client';

class CustomCard extends HTMLElement {
    connectedCallback() {
        this.textContent = `Start: ${this.getAttribute('start')}`;
    }
}

customElements.define('custom-card', CustomCard);

render({
    id: 'custom',
    target: document.querySelector('#root'),
    json: {
        card: {
            log_id: 'custom_card',
            states: [
                {
                    state_id: 0,
                    div: {
                        type: 'custom',
                        custom_type: 'custom_card',
                        custom_props: {
                            start: 15
                        }
                    }
                }
            ]
        }
    },
    customComponents: new Map([
        ['custom_card', { element: 'custom-card' }]
    ])
});
```

Properties from `custom_props` are passed to the component as HTML attributes. Custom components are also supported in server-side rendering: you can pass the component markup for the server in the `template` field of the description.

Examples on GitHub:

- [Simple component](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/custom-simple).
- [Component with DivKit child elements](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/custom-container).
- [Component and server-side rendering](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/custom-ssr).

### Extensions {#extensions}

No extensions are enabled by default. To enable an extension, pass a `Map` in the `extensions` parameter: the key is the extension identifier from the element's `extensions` field, and the value is the extension class. The `client` and `client-hydratable` modules export the ready-made `SizeProvider` and `Gesture` extensions, as well as the `lottieExtensionBuilder` and `markdownExtensionBuilder` functions that create extensions for Lottie and Markdown.

```js translate=no
import { render, SizeProvider } from '@divkitframework/divkit/client';

render({
    id: 'hello',
    target: document.querySelector('#root'),
    json,
    extensions: new Map([
        ['size_provider', SizeProvider]
    ])
});
```

Extensions work on the client only. If the page is rendered on the server and an extension changes the look of an element, users may notice this change while the page loads.

For more information about extensions and the `extensionsForAllComponents` parameter, see [Connection](https://divkit.tech/docs/en/concepts/extensions.md#connect).

### Fonts {#fonts}

Fonts are added to the page using CSS. To map a font name from the `font_family` parameter to a CSS font, pass the `typefaceProvider` function. It receives the font name and an optional object with the `fontWeight` weight and returns the value of the `font-family` CSS property:

```js translate=no
render({
    id: 'hello',
    target: document.querySelector('#root'),
    json,
    typefaceProvider(fontFamily, opts) {
        if (fontFamily === 'display') {
            return '"My Display Font", sans-serif';
        }

        return '';
    }
});
```

For more information, see [Fonts](https://divkit.tech/docs/en/quickstart/resources.md#fonts-web).

## Updating and destroying a card {#instance}

The `render` function from the `client` and `client-hydratable` modules returns a card instance. Its methods:

| Method | Description |
| --- | --- |
| `execAction(action)` | Executes an [action](../concepts/interaction.md) in the card. |
| `applyPatch(patch)` | Applies a [patch](../concepts/patches.md#patch-format). Returns `true` if the patch is applied. |
| `setData(json)` | Redraws the card using new JSON. The method is experimental: its logic and API may change. |
| `$destroy()` | Destroys the instance and removes the card from the page. |

```js translate=no
instance.execAction({
    log_id: 'reset_counter',
    url: 'div-action://set_variable?name=counter&value=0'
});

instance.$destroy();
```

The `setData` method tries to preserve the card state, such as the values of input fields. It doesn't change existing variables or triggers and only creates new variables.

## Environment requirements {#requirements}

Supported browsers:

```translate=no
chrome >= 67
safari >= 14
firefox >= 68
```

Some features require more modern browsers. For example, the `aspect` parameter of the `container` element requires support for the `aspect-ratio` CSS property.

For server-side rendering:

```translate=no
Node.js >= 14
```

DivKit stores integers in the `BigInt` type if the platform supports it. Keep in mind that `JSON.parse` and the `json()` method of a `fetch` response return large integers as `number`, so values greater than `2^53` may lose precision even before they are passed to DivKit.

## Sample projects {#samples}

Ready-to-run examples are available on [GitHub](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples):

- [js](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/js) and [ts](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/ts): Usage with a build.
- [globals](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/globals) and [globals-esm](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/globals-esm): Usage without a build.
- [ssr](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/ssr) and [node-esm](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/node-esm): Server-side rendering.
- [divkit-react](https://github.com/divkit/divkit/tree/main/client/web/divkit-examples/divkit-react): React with server-side rendering.

<!-- source: en/_includes/index/troubleshooting.md -->
## Learn more {#troubleshooting}

You can discuss topics of interest in the DivKit user community in Telegram: [https://t.me/divkit_community_en](https://t.me/divkit_community_en).



[DivKit Repository](https://github.com/divkit/divkit)
<!-- endsource: en/_includes/index/troubleshooting.md -->
