Custom Fonts

DivKit allows you to use custom fonts in your application. This makes it possible to maintain a consistent text style across all platforms and ensure compliance with your application's design.

General Concept

To use custom fonts in DivKit, you need to:

  1. Add fonts to your application resources
  2. Implement a font provider for the corresponding platform
  3. Pass the font provider to DivKit during initialization
  4. Use font names in DivKit JSON markup

In DivKit JSON markup, fonts are specified in the font_family parameter of the div-text element:

Sample code
{
  "type": "text",
  "font_family": "MyCustomFont",
  "font_weight": 500,
  "text": "Text with custom font"
}

The font_weight parameter defines the font thickness and can take the following values:

  • 100 - Thin
  • 200 - Extra Light
  • 300 - Light
  • 400 - Regular (default value)
  • 500 - Medium
  • 600 - Semi Bold
  • 700 - Bold
  • 800 - Extra Bold
  • 900 - Black

Android

On the Android platform, to use custom fonts, you need to implement the DivTypefaceProvider interface.

DivTypefaceProvider Implementation

import android.content.Context;
import android.graphics.Typeface;
import androidx.annotation.Nullable;
import com.yandex.div.core.font.DivTypefaceProvider;

public class CustomTypefaceProvider implements DivTypefaceProvider {
    private final Context context;

    // Cache fonts to improve performance
    private Typeface regularTypeface;
    private Typeface mediumTypeface;
    private Typeface lightTypeface;
    private Typeface boldTypeface;

    public CustomTypefaceProvider(Context context) {
        this.context = context;
    }

    @Nullable
    @Override
    public Typeface getRegular() {
        if (regularTypeface == null) {
            regularTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/MyFont-Regular.ttf");
        }
        return regularTypeface;
    }

    @Nullable
    @Override
    public Typeface getMedium() {
        if (mediumTypeface == null) {
            mediumTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/MyFont-Medium.ttf");
        }
        return mediumTypeface;
    }

    @Nullable
    @Override
    public Typeface getLight() {
        if (lightTypeface == null) {
            lightTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/MyFont-Light.ttf");
        }
        return lightTypeface;
    }

    @Nullable
    @Override
    public Typeface getBold() {
        if (boldTypeface == null) {
            boldTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/MyFont-Bold.ttf");
        }
        return boldTypeface;
    }

    // Optional: override the getTypefaceFor method for more precise control
    // over font weight matching
    @Nullable
    @Override
    public Typeface getTypefaceFor(int weight) {
        if (weight >= 0 && weight < 350) {
            return getLight();
        } else if (weight >= 350 && weight < 450) {
            return getRegular();
        } else if (weight >= 450 && weight < 650) {
            return getMedium();
        } else {
            return getBold();
        }
    }
}

Integration into Application

import com.yandex.div.core.Div2Context;
import com.yandex.div.core.DivConfiguration;

// When initializing DivKit
DivConfiguration configuration = new DivConfiguration.Builder()
    .typefaceProvider(new CustomTypefaceProvider(context))
    // other settings
    .build();

Div2Context div2Context = Div2Context.create(
    context,
    configuration
);

iOS

On the iOS platform, to use custom fonts, you need to implement the DivFontProvider protocol.

Adding Fonts to the Project

  1. Add font files (.ttf or .otf) to your project
  2. Make sure the fonts are included in the application resources (Bundle Resources)
  3. Add font information to Info.plist in the Fonts provided by application section:
<key>UIAppFonts</key>
<array>
    <string>MyFont-Regular.ttf</string>
    <string>MyFont-Medium.ttf</string>
    <string>MyFont-Light.ttf</string>
    <string>MyFont-Bold.ttf</string>
</array>

DivFontProvider Implementation

import UIKit
import DivKit
import VGSL

class CustomFontProvider: DivFontProvider {
    func font(family: String, weight: DivFontWeight, size: CGFloat) -> Font {
        // If a specific font family is specified
        if family == "MyCustomFont" {
            let fontName: String
            switch weight {
            case .light:
                fontName = "MyFont-Light"
            case .regular:
                fontName = "MyFont-Regular"
            case .medium:
                fontName = "MyFont-Medium"
            case .bold:
                fontName = "MyFont-Bold"
            }

            if let font = UIFont(name: fontName, size: size) {
                return Font(uiFont: font)
            }
        }

        // Return system font if custom font is not found
        let uiFont: UIFont
        switch weight {
        case .light:
            uiFont = UIFont.systemFont(ofSize: size, weight: .light)
        case .regular:
            uiFont = UIFont.systemFont(ofSize: size, weight: .regular)
        case .medium:
            uiFont = UIFont.systemFont(ofSize: size, weight: .medium)
        case .bold:
            uiFont = UIFont.systemFont(ofSize: size, weight: .bold)
        }

        return Font(uiFont: uiFont)
    }

    // The method for getting a font by numerical weight is already implemented in the protocol extension
}

Integration into Application

import DivKit

// When initializing DivKit
let components = DivKitComponents(
    divCustomBlockFactory: nil,
    fontProvider: CustomFontProvider(),
    // other parameters
)

Web

On the Web platform, to use custom fonts, you need to:

  1. Connect fonts using standard CSS methods (via @font-face or external services)
  2. Use the typefaceProvider parameter when initializing DivKit

Connecting Fonts via CSS

The font family in CSS does not have to match the name in JSON.

Don't forget to provide all the styles and weights options that you will need in your markup (in this example, 400, 500, and 700 are added). Another option is to use variable fonts.

@font-face {
  font-family: 'MyCustomFont';
  src: url('fonts/MyFont-Regular.woff2') format('woff2'),
       url('fonts/MyFont-Regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
}

@font-face {
  font-family: 'MyCustomFont';
  src: url('fonts/MyFont-Medium.woff2') format('woff2'),
       url('fonts/MyFont-Medium.woff') format('woff');
  font-weight: 500;
  font-style: normal;
}

@font-face {
  font-family: 'MyCustomFont';
  src: url('fonts/MyFont-Bold.woff2') format('woff2'),
       url('fonts/MyFont-Bold.woff') format('woff');
  font-weight: 700;
  font-style: normal;
}

Using typefaceProvider

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

render({
    id: 'my-divkit-container',
    target: document.querySelector('#root'),
    json: {
        card: {
            log_id: 'custom_fonts_example',
            states: [{
                state_id: 0,
                div: {
                    type: 'text',
                    font_family: 'MyCustomFont',
                    font_weight: 500,
                    text: 'Text with custom font'
                }
            }]
        }
    },
    typefaceProvider: (fontFamily, opts) => {
        // You can implement mapping of font names from JSON to CSS
        if (fontFamily === 'MyCustomFont') {
            return 'MyCustomFont, sans-serif';
        }

        // For the default option, you can return an empty string.
        return '';
    }
});

Usage Examples in JSON

Basic Example

Sample code
{
  "type": "text",
  "font_family": "MyCustomFont",
  "font_weight": 400,
  "text": "Text with custom font"
}

Different Font Styles

Sample code
{
  "type": "container",
  "items": [
    {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 300,
      "text": "Text with light font (Light)"
    },
    {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 400,
      "text": "Text with regular font (Regular)"
    },
    {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 500,
      "text": "Text with medium font (Medium)"
    },
    {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 700,
      "text": "Text with bold font (Bold)"
    }
  ]
}

Using in Templates

Sample code
{
  "templates": {
    "title": {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 700,
      "font_size": 20,
      "$text": "title"
    },
    "body": {
      "type": "text",
      "font_family": "MyCustomFont",
      "font_weight": 400,
      "font_size": 16,
      "$text": "text"
    }
  },
  "card": {
    "log_id": "custom_fonts_example",
    "states": [
      {
        "state_id": 0,
        "div": {
          "type": "container",
          "items": [
            {
              "type": "title",
              "text": "Heading with custom font"
            },
            {
              "type": "body",
              "text": "Body text with custom font"
            }
          ]
        }
      }
    ]
  }
}

Recommendations

  1. Performance Optimization: Cache font instances to avoid reloading.
  2. Support for Different Weights: Implement support for different font weights to ensure design flexibility.
  3. Fallback Options: Always provide fallback font options in case the custom font fails to load.
  4. Font Preloading: For the web platform, it is recommended to preload fonts to avoid text flickering when the page loads.
  5. Testing: Check font rendering on various devices and under different conditions to ensure correct display.

Learn more

Follow DivKit news in the Telegram channel: http://t.me/divkit_news

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

DivKit Repository