skip to Main Content

Is it possible to get the filename of the rendered font of an element?

Example:

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

@font-face {
  font-family: 'MyFont';
  src: url('../../public/fonts/MyFont-Italic.woff2') format('woff2');
  font-weight: normal;
  font-style: italic;
}

.my-font-bold {
 font-family: 'MyFont';
 font-weight: bold;
 font-style: normal;
}

<p className="my-font-bold"></p>

In this example I would like to get ../../public/fonts/MyFont-Bold.woff2 of the element (because it has font-weight bold and font-family = "MyFont" thanks to the className "my-font-bold").

PS: I would like to do this to make font Vitest tests.

CodeSandbox: https://codesandbox.io/p/sandbox/magical-flower-q87vz7?file=%2Fapp%2Ffont.test.tsx%3A27%2C2

2

Answers


  1. In Javascript it is definitely possible. You just need to leverage the getComputedStyle to achieve that.

    Steps to achieve the requirement:

    1. Get the font name of the font that p tag is using.
    2. Get all the css rules associated with the document as an array.
    3. Filter out the font-family based on step 1.
    4. If the fontFaceRule exists, extract the url and return the result else return null.
    5. Post this you can write the test for this helper function in jest.

    Code implementation:

    function getRenderedFontUrl(element) {
      const fontFamily = window.getComputedStyle(element).getPropertyValue('font-family').replace(/['"]/g, '');
      const cssRules = Array.from(document.styleSheets).flatMap(sheet => Array.from(sheet.cssRules));
    
      const fontFaceRule = cssRules.find(rule => {
        return rule.type === CSSRule.FONT_FACE_RULE && rule.style.getPropertyValue('font-family') === fontFamily;
      });
      
    
      if (fontFaceRule) {
        const src = fontFaceRule.style.getPropertyValue('src');
        const urlRegex = /url((['"]?)(.*?)1)/g;
        const match = urlRegex.exec(src);
        return match ? match[2] : null;
      }
    
      return null;
    }
    
    // Usage example
    const paragraphElement = document.querySelector('p');
    const fontUrl = getRenderedFontUrl(paragraphElement);
    console.log(fontUrl);
    @font-face {
      font-family: 'MyFont';
      src: url('../../public/fonts/MyFont-Bold.woff2') format('woff2');
      font-weight: bold;
      font-style: normal;
    }
    
    @font-face {
      font-family: 'MyFont';
      src: url('../../public/fonts/MyFont-Italic.woff2') format('woff2');
      font-weight: normal;
      font-style: italic;
    }
    
    .my-font-bold {
     font-family: 'MyFont';
     font-weight: bold;
     font-style: normal;
    }
    <p style="font-family: 'MyFont'; font-weight: bold;">

    Writing the test for the above function:

    import { JSDOM } from 'jsdom';
    import { getRenderedFontUrl } from './path-where-you-defined';
    
    const { window } = new JSDOM();
    global.window = window;
    global.document = window.document;
    
    describe('getRenderedFontUrl', () => {
      beforeEach(() => {
        document.head.innerHTML = `
          <style>
            @font-face {
              font-family: 'MyFont';
              src: url('../../public/fonts/MyFont.woff2') format('woff2');
              font-weight: 300;
              font-style: normal;
            }
    
            p {
              font-family: 'MyFont';
            }
          </style>
        `;
      });
    
      it('should return font URL for an element with', () => {
        const pElement = document.createElement('p');
        document.body.appendChild(pElement);
    
        const fontUrl = getRenderedFontUrl(pElement);
        expect(fontUrl).toBe('../../public/fonts/MyFont.woff2');
      });
    
      it('should return null for an element without', () => {
        const divElement = document.createElement('div');
        document.body.appendChild(divElement);
    
        const fontUrl = getRenderedFontUrl(divElement);
        expect(fontUrl).toBeNull();
      });
    });
    
    Login or Signup to reply.
  2. There is no direct way to access the filename of the rendered font in a web browser. JavaScript running in a browser is intentionally sandboxed and doesn’t have access to low-level system file details for security reasons. If you need to verify which font is being used on a particular element for testing purposes, you can examine its computed styles using JavaScript.

    The following example will check the font-family for an element:

    const element = document.querySelector(".my-font-bold");
    const computedStyle = window.getComputedStyle(element);
    const fontFamily = computedStyle.getPropertyValue("font-family");
    
    console.log("Computed font-family:", fontFamily);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search