<div id="root"></div>
body {
  height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
}
.container {
  width: 300px;
}
.text {
  font-size: 40px;
}
View Compiled
const convertFontFiletoBase64 = async (file: File) => {
  const result_base64 = await new Promise((resolve) => {
    const fileReader = new FileReader();
    fileReader.onload = () => resolve(fileReader.result);
    fileReader.readAsDataURL(file);
  });
  return result_base64 as string;
};

const onFileInput = async (e: SyntheticEvent<HTMLInputElement, Event>) => {
  const { files } = e.currentTarget;
  if (files && files?.length > 0) {
    const font = await convertFontFiletoBase64(files[0]);

    // @ts-ignore because FontFace is experimental and not yet supported by TS.
    const fontFace = new FontFace("uploadedFont", `url(${font})`);
    (document as any).fonts.add(fontFace);
    await fontFace.load();
  }
};

const App = () => {
  return (
    <div className="container">
      <input type="file" onInput={onFileInput} accept={".ttf"} />
      <span className="text" style={{ fontFamily: "uploadedFont" }}>
        Sample Text
      </span>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
View Compiled
Run Pen

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css

External JavaScript

  1. https://unpkg.com/react@16.7.0-alpha.0/umd/react.production.min.js
  2. https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.production.min.js