Home > Software design >  How to get filename of the rendered font CSS?
How to get filename of the rendered font CSS?

Time:11-05

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=/app/font.test.tsx:27,2

CodePudding user response:

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();
  });
});

CodePudding user response:

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);
  • Related