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.

Connecting the library and rendering the first card

Installing the package

Install the package from npm:

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

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:

import '@divkitframework/divkit/dist/client.css';

Or link the file in the HTML page:

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

Rendering on the client

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

<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:

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.

Server-side rendering and hydration

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

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:

import { render } from '@divkitframework/divkit/client-hydratable';

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

Note

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.

A ready-made example of server-side rendering with hydration is available on GitHub.

Using the library without a build

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

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

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

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

<script type="module">
    import { render } from './node_modules/@divkitframework/divkit/dist/esm/client.mjs';

    render({
        id: 'hello',
        target: document.querySelector('#root'),
        json: {
            card: {
                log_id: 'text',
                states: [
                    {
                        state_id: 0,
                        div: {
                            type: 'text',
                            text: 'Hello, DivKit!'
                        }
                    }
                ]
            }
        }
    });
</script>

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

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

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

<script src="./node_modules/@divkitframework/divkit/dist/browser/client.js"></script>
<script>
    window.Ya.DivKit.render({
        id: 'hello',
        target: document.querySelector('#root'),
        json: {
            card: {
                log_id: 'text',
                states: [
                    {
                        state_id: 0,
                        div: {
                            type: 'text',
                            text: 'Hello, DivKit!'
                        }
                    }
                ]
            }
        }
    });
</script>

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

React

For React, there is a separate package: @divkitframework/react. Its DivKit component accepts the render function parameters as props.

Parameters of the render function

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.

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.
onStat client, client-hydratable function. Handler for logging clicks and impressions. See Statistics.
onCustomAction client, client-hydratable function. Handler for actions that DivKit doesn't execute itself. See 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.
themeVariableName All string. Name of the variable that stores the current theme. See Theming.
globalVariablesController client, client-hydratable object. Controller of global variables. See Variables.
typefaceProvider All function. Returns the value of the font-family CSS property for a font from the layout. See Fonts.
customComponents All Map. Descriptions of custom components. See Custom components.
extensions client, client-hydratable Map. Extensions that the layout enables by identifier. See Extensions.
extensionsForAllComponents client, client-hydratable array. Extensions that are applied to every element. See 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. 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

Custom actions

To make the interface interactive, add action 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:

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

Handle this action in onCustomAction:

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.

Statistics

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 fired.
render({
    id: 'hello',
    target: document.querySelector('#root'),
    json,
    onStat(details) {
        console.log(details.type, details.action.log_id);
    }
});

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.

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

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

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: when the theme changes, the properties that depend on it are updated without reloading the page.

Note

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.

render({
    id: 'themed',
    target: document.querySelector('#root'),
    json,
    theme: 'system',
    themeVariableName: 'theme'
});
View layout example
{
    "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'}"
                        }
                    ]
                }
            }
        ]
    }
}

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

The client and client-hydratable modules export functions for working with global variables. 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.

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

Custom components

The custom 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:

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:

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.

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.

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:

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.

Updating and destroying a card

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

Method Description
execAction(action) Executes an action in the card.
applyPatch(patch) Applies a patch. 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.
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

Supported browsers:

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:

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

Ready-to-run examples are available on GitHub:

Learn more

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

DivKit Repository

Previous