Incorporate Arabic typography into the React Material Theme

My goal is to utilize the Noto Sans Arabic font within my React material UI theme. Everything seems to be functioning correctly, including overrides.

Despite consulting the React Material UI documentation and attempting to follow similar steps as outlined in other resources, I am unable to successfully import the font:

import notoArabic from '../static/fonts/NotoSansArabic-Regular.ttf'

....


const arabic = {
  fontFamily: 'Noto Sans Arabic',
  fontStyle: 'regular',
  fontDisplay: 'swap',
  fontWeight: 400,
  src: `
    local('Noto Sans Arabic'),
    local('Noto Sans Arabic-Regular'),
    url(${notoArabic}) format('ttf')
  `,
  unicodeRange:
    'U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF',
};

...

overrides: {
    MuiCssBaseline: {
      '@global': {
        '@font-face': [arabic],
      },
    },

...

Although I have ensured that there are no errors present and can confirm the styling rules in my browser reflect "font-family: Noto Sans Arabic;", it appears that the font is still not displaying as expected.

Answer №1

In my native language Persian, our fonts bear a striking resemblance to Arabic fonts. To accommodate this in my project, I created a dedicated file called globalStyles.js:

import { createStyles } from '@material-ui/core';
import yekanRegularTtf from '../app/assets/font/iranyekanwebregular.ttf';
import yekanRegularWoff from '../app/assets/font/iranyekanwebregular.woff';
import yekanRegularWoff2 from '../app/assets/font/iranyekanwebregular.woff2';
import yekanBoldTtf from '../app/assets/font/iranyekanwebbold.ttf';
import yekanBoldWoff from '../app/assets/font/iranyekanwebbold.woff';
import yekanBoldWoff2 from '../app/assets/font/iranyekanwebbold.woff2';

const globalStyles = ({ spacing, typography, colors }) =>
  createStyles({
    '@global': {
      '@font-face': [
        {
          fontFamily: 'IRANYekan',
          fontStyle: 'normal',
          fontWeight: 400,
          src: `url(${yekanRegularWoff2}) format('woff2')`,
          fallbacks: {
            src: [
              `url(${yekanRegularWoff})`,
              `url(${yekanRegularTtf}) format('truetype')`,
            ],
          },
        },
        {
          fontFamily: 'IRANYekan',
          fontStyle: 'normal',
          fontWeight: 700,
          src: `url(${yekanBoldWoff2}) format('woff2')`,
          fallbacks: {
            src: [
              `url(${yekanBoldWoff})`,
              `url(${yekanBoldTtf}) format('truetype')`,
            ],
          },
        },
      ],
      html: {
        lineHeight: '1.5',
        WebkitTextSizeAdjust: '100%',
      },
      '*': {
        transition: 'opacity 1s cubic-bezier(0.4, 0, 0.2, 1)',
        fontFamily: "'IRANYekan', sans-serif, Arial",
        boxSizing: 'border-box',

        '&:after, &:before': {
          fontFamily: "'IRANYekan', sans-serif, Arial",
          boxSizing: 'border-box',
        },
        '&[type="checkbox"], &[type="radio"]': {
          boxSizing: 'border-box',
          padding: '0',
        },
        // Continue with the rest of the CSS styles...
      },
      body: {
        fontFamily: "'IRANYekan', sans-serif, Arial",
        lineHeight: '1.38',
        margin: 0,
      },
      // Continue with the rest of the CSS styles...
    },
  });

export default globalStyles;

To integrate these styles into my project, I injected them into the root component at the top level of my components:

import React from 'react';
import { Provider as ReduxProvider } from 'react-redux';
import { CssBaseline, withStyles } from '@material-ui/core';
import { Helmet } from 'react-helmet';
import SnackBarProvider from './SnackBar';
import globalStyles from '../utils/globalStyles';
import { generalHelmet } from '../utils/helmetConfig';

type AppProviderProps = {
  children: any,
  store: any,
};

const AppProvider = ({ children, store }: AppProviderProps) => (
  <>
    <Helmet {...generalHelmet} />
    <CssBaseline />
    <ReduxProvider store={store}>
      <SnackBarProvider>{children}</SnackBarProvider>
    </ReduxProvider>
  </>
);

export default withStyles(globalStyles)(AppProvider);

In addition, I configured the font loader in my Webpack configuration file as follows:

~~~

const nodeEnv = process.env.NODE_ENV || 'development';
const isDev = nodeEnv === 'development';
const exclude = [/node_modules/, /public/];
const name = isDev ? '[name].[ext]' : '[hash:5].[ext]';
const publicPath = '/assets/';

~~~

module.exports = {

  ~~~

  module: {
    rules: [

      ~~~

      {
        test: /\.(woff2?|ttf|eot|svg)$/,
        exclude,
        loader: 'url',
        options: { limit: 10240, name, publicPath },
      },

With all these configurations in place, everything is functioning smoothly now. I hope this setup proves helpful for you.

Answer №2

To ensure your code is compiling correctly, consider these steps:

  1. If the font you are importing has a URL that references the static folder and the directory containing the file as siblings, make sure the path matches the structure of the root folder.

  2. If you are using webpack to bundle your code, remember to include the ttf file extension in the configuration and add the file-loader module to handle it during compilation. You can find more information on how to set up the file-loader here.

For example:

{
  test: /\.(png|jpg|gif|svg|ttf|eot|woff)$/,
  loader: 'file-loader',
  query: {
    name: '[name].[ext]?[hash]'
  }
},

Answer №3

If you're experiencing issues with loading a particular font, consider adding the font directly to your index.css file and verifying if that resolves the problem. It's possible that the specified font location is incorrect or that the font itself is not available.

Another potential solution could be utilizing a file-loader or plugin when working with webpack to ensure proper font rendering. You can learn more about this process here:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Oops! Looks like we encountered an issue with the digital envelope routines on react 16 and node 21

Encountered an error while trying to run yarn start on a year-old React project. Error: error:0308010C:digital envelope routines::unsupported at new Hash (node:internal/crypto/hash:80:19) at Object.createHash (node:crypto:139:10) at module.expo ...

Remove advertisements from a website on an Android device using Java programming

Currently, I am developing an application that will open a webpage within a webview. I have the ability to retrieve the HTML content from the page, and in order to improve loading speed, I am attempting to remove any ads present on the webpage. Despite e ...

Issues with the aligning of buttons using the justify-content property

The issue I'm facing involves a parent container with 3 buttons nested inside. The parent container is set to display:inline-flex, however, the justify-content: space-between property is not behaving as expected. Each button has a defined max-width in ...

Error encountered during the prerendering process on Vercel's Next.js build

While trying to compile my website on Vercel, I encountered a pre-rendering error during export. Does anyone know why this is happening and can provide assistance? Here is the link to my GitHub repository where all the code is stored: https://github.com/M ...

Implementing the #toolbar=0 parameter to the src attribute of a PDF file in ReactJS

Is there a way to display a PDF in a modal window without the toolbar appearing? The current method I am using involves importing the PDF as a variable and then appending #toolbar=0 to the end of the URL. However, I cannot figure out how to properly append ...

"Transitioning from jQuery to Vanilla Javascript: Mastering Scroll Animations

I'm seeking guidance on how to convert this jQuery code into pure Javascript. $('.revealedBox').each(function() { if ($(window).scrollTop() + $(window).height() > $(this).offset().top + $(this).outerHeight()) { $(this).addCla ...

Signature incorporating visual elements in emails

I am attempting to create an HTML + Images Signature in Mozilla Thunderbird. I understand that this may not be the most ideal software for designing email signatures, but I am looking for a free alternative. While my image is attached to the email itself ...

Learn the steps to navigate the user to a different tab panel on the same page using ReactJS

I'm working on an authentication page with an <AppBar> that has two <TabPanel>s. After a user submits their information in the register tab, I want to automatically redirect them to the login tab. I've tried looking for a solution to ...

Having trouble setting the CSS width to 100%

Is there a way to assert the CSS width of an element in NightwatchJS to be 100% without hard-coding the value? Currently, when I attempt to do so, it fails and reports that the width is 196px. The specific error message is as follows: Testing if element ...

Toggling forms with HTML <select> elements: A step-by-step guide

In the process of creating a web application, I am faced with the task of registering users based on their specific category. To accomplish this, I have incorporated a combo-box where users can indicate their user type. My objective is to display an appro ...

Is there a way for me to view the specifics by hovering over a particular box?

Whenever I hover over a specific box, detailed information appears, and when I move the mouse away, the details disappear. HTML <nav> <div> <div class="nav-container"> <a href="./about.html" ...

Title vanishes when gradient is added to a div

I have encountered an issue with a recent update on my webpage. Previously, I had multiple divs with the title attribute that displayed information when users hovered over them. However, after adding a gradient background, the titles stopped appearing. Th ...

Simple steps to dynamically alter CSS styles according to the current URL

I am working on a website where I want users to be able to change the background image and other CSS elements. Currently, my approach is to have multiple HTML pages that users can switch between using a dropdown menu and reload the page. For example: hre ...

CSS for the root folder of an ASP.NET website

After deciding to venture into ASP.NET, I quickly encountered my first obstacle. The folder structure is as follows: \ ->Admin -->Admin.Aspx ->CSS -->Style.css ->Images -->bg.gif Default.aspx Default.master Both admin.aspx and ...

Can these two arrays be merged together in JavaScript?

Here is the structure of the first array: [ 0:{program: id_1}, 1: {program: id_2} ] Now, let's take a look at the second array: [ 0: [ 0: {lesson: name_1}, 1: {lesson: name_2} ], 1: [ 0: {lesson: name_3} ] ] I am attempti ...

Tips on showing a specific div when a button is clicked using jQuery and Bootstrap

In my button group, I have four buttons and I need one specific button to display certain div content when clicked. The displayed content should be based on which button is clicked. Is there a way to achieve this using Twitter Bootstrap jQuery in ASP.NET ...

"Upon exiting the Chrome tab on an iPhone, the Opentok stream's hasAudio property returns false

While switching to a different tab in Chrome on iPhone (without closing it), the publisher's stream.hasAudio value changes to false. It switches back to true only upon returning to the stream tab. Can anyone explain why this occurs and how to stop has ...

Set the webpage to a fixed width

Is there a way to make my webpage fixed-width instead of liquid? I've tried changing the container size to pixels but the text still collapses when I resize the browser. Any suggestions on how to keep it at a fixed width? <!DOCTYPE html PUBLIC "-/ ...

Displaying the current time and total time of a custom video player using Javascript

Currently, I'm in the process of creating an html5 video player and have incorporated javascript to update the current time as a fraction of the total time. The script I've written so far is as follows: function updateTime() { var curTime = ...

The plugin data containing 'data:application/pdf;base64,JVBERi0xLjQKJ**' was declined for loading. Content security policy cannot be configured

My approach to enforcing content security policy involves using the following code snippet: <meta charset="UTF-8" http-equiv="content-security-policy" content="object-src 'self' data:" /> However, when this i ...