Tips on locating the various font-weights offered in a personalized font CSS document

I am currently developing a unique feature that allows users to upload a .css file and utilize it within our editor. To achieve this, I need to identify the various font-weight values present in the file, so that they can be displayed in a dropdown list in the editor.

I am seeking suggestions on the best approach to determine the font-weight options available for the custom font. Since the user will be uploading the file, I will not have prior knowledge of the font-weights used.

User Input:

/* latin */
@font-face {
  font-family: 'Poppins';
  font-style: italic;
  font-weight: 200;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
}
/* devanagari */
@font-face {
  font-family: 'Poppins';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLm21lVFteOYktMqlap.woff2) format('woff2');
}
/* latin */
@font-face {
  font-family: 'Poppins';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
}

Required Data: [200, 300, 400]

Seeking solution using JavaScript.

Answer №1

Big shoutout to @herrstrietzel for providing the solution above!

Instead of the traditional method of creating a style tag with an id and disabling it, I opted to utilize CSSStyleSheet() in my code implementation.

/**
 * Here lies the CSS content
 * fetched using fileReader/input
 */
let cssText = `
 /* latin */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 200;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  }

  /* latin */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  }

  /* latin-ext */
  @font-face {
    font-family: 'Agdasima';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/agdasima/v2/PN_0Rfyxp2f1fUCgAPCGgCza3v3xzHMj54Y.woff2) format('woff2');
  }
`;

let cssSheet = new CSSStyleSheet()
cssSheet.replaceSync(cssText)

let rules = [...cssSheet.cssRules]
let fontProps = []
rules.forEach((rule) => {
  let type = rule.type

  // type 5 represents @font-face
  if (type === 5) {
    let fontFamily = rule.style.getPropertyValue("font-family")
    let fontStyle = rule.style.getPropertyValue("font-style")
    let fontWeight = rule.style.getPropertyValue("font-weight")
    fontProps.push({
      fontFamily: fontFamily,
      fontWeight: fontWeight,
      fontStyle: fontStyle
    })
  }
})
console.log(fontProps)

Answer №2

To extract properties from your uploaded CSS text, one approach is to add the text to the document stylesheets and access all properties using document.styleSheets and cssRules.

When adding a new stylesheet, it's crucial not to overwrite the existing app/page styles. Thus, disabling the new stylesheet or style rules becomes necessary.

Demonstration: load content into <style> element and disable it

/**
 * Here's some example CSS content
 * obtained through fileReader/input
 */
let cssText = `
 /* latin */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 200;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiDyp8kv8JHgFVrJJLmv1pVF9eOYktMqg.woff2) format('woff2');
  }

  /* latin */
  @font-face {
    font-family: 'Poppins';
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/poppins/v20/pxiGyp8kv8JHgFVrJJLucHtAOvWDSA.woff2) format('woff2');
  }

  body {
    font-family: Poppins;
    font-style: italic;
    background: red;
  }
`;

/**
 * Load disabled
 * style element with
 * new css rules for parsing
 */
cssTmp.textContent = cssText;

/**
 * Retrieve temporary stylesheet by id
 * and deactivate it
 * to avoid altering the UI style of the application
 */
let stylesheetTmp = [...document.styleSheets].filter((style) => {
  return style.ownerNode.id == "cssTmp";
})[0];

// Disable stylesheet
stylesheetTmp.disabled = true;

/**
 * Access @font-face rules
 */
let rules = [...stylesheetTmp.cssRules];
let fontProps = [];
rules.forEach((rule) => {
  let type = rule.type;

  // Type 5 represents @font-face
  if (type === 5) {
    let fontFamily = rule.style.getPropertyValue("font-family");
    let fontStyle = rule.style.getPropertyValue("font-style");
    let fontWeight = rule.style.getPropertyValue("font-weight");
    fontProps.push({
      fontFamily: fontFamily,
      fontWeight: fontWeight,
      fontStyle: fontStyle
    });
  }
});

console.log(fontProps);
<style id="cssTmp"></style>
<p>Test</p>

Functionality Breakdown

  1. Create a <style> element with a unique ID like "cssTmp"
  2. Fill this element with the imported CSS content
    cssTmp.textContent = cssText
  3. Select the stylesheet by filtering all document stylesheets based on the specified ID:
let stylesheetTmp = [...document.styleSheets].filter((style) => {
  return style.ownerNode.id == "cssTmp";
})[0];
  1. Deactivate this stylesheet:
stylesheetTmp.disabled = true;
  1. Iterate through cssRules
    To make the styles rules iterable, employ the spread operator or use Array.from() method.
let rules = [...stylesheetTmp.cssRules];  

By filtering out @font-face rules based on their type - which is "5", you can explore all data within the rule object by including a console.log(rule).

You might require additional property values such as font styles (regular/italic) - these details can be organized in an array of objects created beforehand.

The retrieved data could then populate options within a <select> element.

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

Create fluidly changing pictures within varying div elements

Hello there! I have a form consisting of four divs, each representing a full page to be printed like the one shown here: https://i.sstatic.net/w7N6E.png I've successfully created all the controls using AJAX without any issues. Then, I load the image ...

An error has been detected by Internet Explorer 8 at line number 373402504

Internet Explorer 8 is throwing an error message that seems to be from a different galaxy ("Expected identifier, string or number") at a line number that makes no sense. Surprisingly, the code functions perfectly on FireFox. Checking the source code, I se ...

How can I fill an HTML table with data stored in a JavaScript array of arrays?

I am struggling to populate an HTML table with data formatted as an array of arrays. Despite my efforts in writing the code, the data is only showing up in a single row. I have tried mapping the data in a nested loop but I am unable to implement it correct ...

Dependency injection in Angular is a powerful design pattern that

I recently completed an Angular 2 website, but I've run into some issues that I cannot seem to debug. I've spent the past week trying to find a solution but have had no luck. Below, I've included some snippets of my code. Feel free to ask fo ...

Implementing a universal font-size adjustment feature according to user preferences

Is it possible to allow users to choose the font size for the entire application, offering three options: Big, Medium, Small? If a user selects "Big", all fonts in the application will be resized globally. I have spent time researching this issue but ha ...

Animating a spherical object in 3D space using THREE.js

As a newcomer to THREE.js with limited physics knowledge, I am in the process of developing a top-view football game engine. However, I am currently facing challenges related to the ball's movement. When attempting to move the ball from side to side, ...

JS - reloading the location after a function has been carried out with a short delay

Currently, I am using a JS / AJAX script to update information in my table. After the script finishes running, I want to reload the page. Unfortunately, when using my current code, the page reloads instantly. Is there a way to add a delay of 3 seconds befo ...

When the enter key is pressed, the form will be submitted and the results will be displayed in a modal window without

Behold, my unique form! It lacks the traditional <form></form> tags. <input id="query" name="query" style="font-size: 18pt" id="text" data-email="required" type="text" placeholder="Search Here from <?php echo $row['no']."+"; ?& ...

Transmitting JSON information using post method through .ajax(), as well as receiving a JSON reply

Seeking assistance with debugging a registration page I am currently coding. I have hit a roadblock for the past 48 hours and would greatly appreciate any help in resolving the issues. CHALLENGE I am utilizing JavaScript to validate form inputs for error ...

How to use image source and mouse hover effects in CSS3

Can we create a CSS3 class for the src, onmouseout, and onmousehover properties? <img src="http://www.example.com//images/pic.png" onmouseout="this.src = 'http://www.example.com/images/pic.png'" onmouseover="this.src = 'http://www.examp ...

What is the best way to ensure that any modifications made to an item in a table are appropriately synced

Utilizing xeditable.js, I am able to dynamically update the content of a cell within a table. My goal is to capture these changes and send them via an HTTP request (PUT) to the backend in order to update the database. Below is the table that can be edited ...

Having trouble getting Javascript to reveal hidden elements based on their class

I am having some trouble making specific fields in a form appear based on the selection made from a dropdown menu. Below is a simplified snippet of my code, which should change the display from 'none' to 'block'. Can you help me figure ...

Automatic Hiding of Dropdown Menu in Twitter Bootstrap: A Quick Guide to Set a 2-Second Timer

Is there a way to make the dropdown menu hide automatically after the mouse cursor leaves the area? If you take a look at Amazon.com for example, when you hover over "Shop by Department" and then quickly move your cursor away and back within about half a ...

Set options for nested arrays with up to n levels of children

My project involves building a category module using Laravel for the backend and Vue.js for the frontend. I have incorporated the library Laravel Nestable The library has been successful in producing the desired output. [ { "id": 1, "name": "C ...

Inexplicably bizarre HTML glitch

I am currently utilizing a comment system that involves adding a new row to a SQL database. The system seems to be working fine; however, when I try to display the comments, the formatting of the comment div becomes all jumbled up. You can view the page wh ...

Troubleshooting border styling problems on an iPad for a table

I'm encountering a CSS issue specifically on iPad devices when rendering the HTML page. Oddly enough, everything appears fine on other browsers. The problem I'm facing is a small space between the cells in my tables as shown in this image: Stran ...

I recently ran npm install --save bootstrap and now I am unable to locate the bootstrap.min.css file anywhere

Trying to follow a tutorial based on a video, I'm running into an issue where I can't locate the bootstrap.min.css file mentioned. Despite searching online, I haven't found any relevant information. The files I have access to are: https://i ...

The functionality of Bootstrap Mobile css is most effective when navigating by scrolling downwards

I am experiencing a strange issue. I am using Ajax to load the Search form. The CSS is being applied correctly, but there is an unusual problem with the bottom margin. The bottom margin only appears when you scroll down in mobile view. When you load the f ...

Is it possible for an onclick attribute to assign a function to document.getElementById without overwriting the existing value?

I want to create a numeric keypad in HTML with numbers 1-9, and I'm unsure if JavaScript can handle an onclick function for each key to show the number in the display div. What would be the most effective way to achieve this? <div id="display"> ...

Two entities positioned on opposite extremes

Is there a way to design a div with two elements (text and image) positioned on opposite sides? The length of the text varies as it's a list of months for selection. Ideally, the text should appear on the left side of the div as a "p" element, while t ...