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:
- Get the font name of the font that
p
tag is using. - Get all the css rules associated with the document as an array.
- Filter out the font-family based on step 1.
- If the fontFaceRule exists, extract the
url
and return the result else returnnull
. - 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);