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

A guide on incorporating user input and output in Javascript using React and Material UI

Currently, I am working on a project that requires ReactJS and Material UI. My main goal is to implement the code provided below in just a single JS file. Is there a way to modify this code to meet my formatting requirements? //js file function calculat ...

I require an HTML <select multiple> element that includes a disabled option

Can anyone help me figure out how to create a multi-select box with a disabled element? I want the box to have the following options: All ----or---- option 1 option 2 I don't want the "----or----" option to be selectable. Here's the code I&a ...

How about creating a fresh variable in Assemble or merging two comparison helpers together?

Is it possible to create a new variable within a partial in Assemble (assemble.io) or combine two comparison helpers? For example: {#is somevar "yes" || anothervar "no"} In my partial, I have HTML that should only display if one of two different variable ...

Putting text on top of an image using Bootstrap

Recently diving into the world of Bootstrap, I have come across a puzzling issue: Take a look at the HTML code from my website: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width ...

A guide to integrating Redux-Saga into a class-based component

I have come up with a concept to organize sagas based on their responsibilities. I've created a parent class for saga handlers like so: export class BaseSagaHandler { static isGenerator(fn) { return fn.endsWith('Gen'); } forkAl ...

How to make an optional prop with a default value non-nullable in a ts+react component?

Is there a way to modify a React component to accept an optional prop and then treat it as non-null within the component itself? For example, consider the following basic component: import React from 'react'; type props = { x?: number; }; c ...

Display PHP output within a styled CSS box

<html> <head> </head> <style type="text/css"> .yellow-box { position:absolute; top:100px; left:500px; width:300px; height:300px; background:yellow } </style> <div class = "yellow-box" > </div ...

Tips for retrieving data from an Excel spreadsheet on an HTML/CSS webpage

I have a single HTML template at this location: . The current page is tailored for the state of Arkansas in the US, but I now need to replicate the design for all 50 states. Each state page will have the same layout, but different content specific to that ...

Unable to include Authenticated Routes in react router dom

Currently, I am utilizing react-router-dom to manage routing for users who are authenticated and non-authenticated. However, I have encountered an error in Element due to missing properties. Is there a way to make withoutAuth() function properly for authe ...

How to display percentage value on ReactJS Material UI progress bar

For displaying the progress completed in numbers, I utilize the Linear Determinate component. Take a look at the image below to see how it appears. ...

In the Shopify Next.js app, the pages are refreshed instead of being routed

I utilized Shopify's tutorial until the completion of the fourth step to create a Next JS app with two embedded pages, Home and Page1. However, when attempting to navigate to either page, instead of routing properly, the app is causing a reload... Yo ...

Rendering issue with component

I am encountered with a situation where one component is failing to render its sub-component. Surprisingly, there are no visible errors in the console. The data I'm expecting from the web call is also coming through without any issues. However, for so ...

Develop a Custom Design using Material-ui and ClojureScript

I have included the material-ui library and used the function createMuiTheme in my code: (:require ["@material-ui/core" :as ui] ["@material-ui/core/styles" :refer [createMuiTheme]]) Then I define the following : (def theme (createMuiTh ...

The code will only detect the browser when accessed from a mobile device, and will display a

I've experimented with various methods to make this work. My website has a streaming radio player at the top of the page, usually using the default script provided: <center> <!--Wavestreaming.com SHOUTcast Flash Player--> <scri ...

Tips for achieving a static background image while allowing scrolling on a webpage in asp.net

I am struggling to implement this on my website. The background image needs to be fixed while the content of the webpage should scroll in asp.net <head runat="server"> <title></title> <style type="text/css"> body { backgr ...

How can I eliminate the default background of Mui tooltip and personalize it in react?

Below is an example of how to customize a nested tooltip within a default background tooltip in MUI. The challenge here is to remove the grey border in the customized tooltip and have only a white background with black text. Check out the code snippet be ...

Create a table that allows one column to have ample space, while ensuring that the other columns have uniform widths

This HTML/CSS creation features the following: https://i.stack.imgur.com/R8PRB.png However, the challenge lies in making the Very Good, Good, Fair, Poor, Very Poor columns equal in width while still allowing the "question" column to adjust its width acco ...

Incorporating the power of ES6 into a pre-existing website using React

I currently have an established website with a page accessible through the URL www.example.com/apps/myApp. The myApp functionality is embedded within an existing HTML page and serves as a utility app. I am interested in learning React, so I see this as a g ...

Tips for creating a navigation system that combines both horizontal and vertical bars

Is there a way for me to have both horizontal and vertical navigation bars on my website? I am new to design and struggling to understand why my CSS isn't working properly when applied to multiple links. <body> <div class="horizontallinks" ...

Mastering the art of reading rows in ASP.NET using Java Script

Within the code snippet below, you'll find an image located in the second column. Clicking on this second column should allow me to access the data stored in the first column. Let's say we have a table with 10 rows. If the user clicks on the ico ...