Close Menu
Trendswave MediaTrendswave Media
  • Home
  • About Us
    • Contact Us
  • Services
  • Influencer Marketing
  • Marketing
  • SEO
  • Social Media
  • Web Design
  • Shop

Subscribe to Updates

Get the latest creative news from Trendswave about Marketing, SEO & Web Design.

Please enable JavaScript in your browser to complete this form.
Loading
What's Hot

Driving Qualified Leads With LinkedIn Content: A Proven Formula

October 3, 2025

Google Ads copywriting with AI: Getting the prompt right

October 3, 2025

A Practical Guide To Building With Clarity (Part 2) — Smashing Magazine

October 3, 2025
Facebook X (Twitter) Instagram
Trendswave MediaTrendswave Media
  • Home
  • About Us
    • Contact Us
  • Services
  • Influencer Marketing
  • Marketing
  • SEO
  • Social Media
  • Web Design
  • Shop
Trendswave MediaTrendswave Media
Home»Web Design»Build your own Typographic Scale tool with JavaScript
Web Design

Build your own Typographic Scale tool with JavaScript

adminBy adminJuly 2, 2025No Comments13 Mins Read
Facebook Twitter Pinterest LinkedIn Tumblr WhatsApp VKontakte Email
Build your own Typographic Scale tool with JavaScript
Share
Facebook Twitter LinkedIn Pinterest Email


The tool will have the following features:

  • Ability to select a font base size
  • Ability to choose different fonts from commonly used Google Fonts
  • Ability to adjust the font weight
  • A live preview for visualizing the typography scaling
  • Ability to generate and copy CSS variables.

So.. what exactly are we building?

Here’s a demo to show what we’re working towards:

Setting up the HTML Structure

Let’s start by setting up the structure in HTML.

1
 

class="container">

2
      
3
         Generator Toolh1>
4
        Create a harmonious type scale for your website
5
      
6
      

class="main">

7
        

class="form-group">

8
          
9
          
10
            type="number"
11
            id="base-size"
12
            value="16"
13
            min="8"
14
            max="32"
15
            step="1"
16
          />
17
        
18
        

class="form-group">

19
          
20
          
21
            
22
          
23
        
24
        

class="form-group">

25
          
26
          
27
            
28
            
29
            
30
            
31
            
32
          
33
        
34
        

class="form-group">

35
          
36
          
37
            
38
            
39
            
40
            
41
            
42
            
43
            
44
            
45
          
46
        
47
        
48
          class="css-output"
49
          type="text"
50
          id="css-output"
51
          style="display: none"
52
        />
53
      
54
      

class="preview-container">

55
        

class="top">

56
          

Preview

57
          
58
        
59
        

class="preview" id="preview">

60
      
61
    

From the HTML structure, you can see we have several select inputs for choosing options such as font family, font weight, and the scale ratio.

We also have a preview container to display the generated type scale in real-time and a button for copying the generated CSS variables.

Our type scale tool consists of 2 sections: the upper section containing the controls, and the bottom section which has the preview container.

Let’s add some basic styling for the body, header, and container.

1
body {
2
    font-family: "inter", sans-serif;
3
    background-color: #f8fafc;
4
    color: #1e293b;
5
    line-height: 1.65;
6
  }
7

8
  .container {
9
    max-width: 1200px;
10
    display: flex;
11
    flex-direction: column;
12
    background-color: white;
13
    margin: 40px auto;
14
    border-radius: 12px;
15
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
16
  }
17
  header {
18
    width: 100%;
19
    padding: 16px;
20
    text-align: center;
21
  }
22

23
 h1 {
24
    font-size: 2rem;
25
    font-weight: 700;
26
    margin-bottom: 8px;
27
  }
28
  header p {
29
    font-size: 1rem;
30
  }
31

32
    

To ensure the inputs are responsive, add flex:wrap to the controls section. 

1
.controls {
2
    display: flex;
3
    flex-wrap: wrap;
4
    gap: 40px;
5
    padding: 32px;
6
    border-bottom: 1px solid #e5e7eb;
7
  }

Next, style the input and select elements.

1
input,
2
  select {
3
    width: 100%;
4
    padding: 8px;
5
    border: 1px solid #e5e7eb;
6
    border-radius: 6px;
7
    font-size: 0.75rem;
8
    font-family: "Inter", sans-serif;
9
    color: #1e293b;
10
  }
11

12
  input:focus,
13
  select:focus {
14
    outline: none;
15
    border-color: #8a8a9081;
16
  }

Apply the following styles to the preview container to ensure it’s scrollable on small screens.

1
.preview-container {
2
    overflow-x: auto;
3
    white-space: nowrap;
4
    display: flex;
5
    flex-direction: column;
6
    background-color: white;
7
    border-radius: 6px;
8
    padding: 0 24px;
9
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
10
  }

From the final result, you can see we have labels in px and rem, as well as a paragraph for displaying each font level. All these elements will be contained within a div with the class scale-item.

Style the item as follows:

1
.scale-item {
2
    display: flex;
3
    align-items: baseline;
4
    margin-bottom: 24px;
5
  }
6

7
  .scale-item p {
8
    margin: 0;
9
  }
10

11
  .scale-label {
12
    width: 80px;
13
    font-size: 0.75rem;
14
    color: #64748b;
15
    flex-shrink: 0;
16
  }

Finally, the Copy CSS button will have the following styles.

1
.copy-css {
2
    position: absolute;
3
    top: 20px;
4
    right: 20px;
5
    background-color: #e9ecef;
6
    padding: 6px 12px;
7
    border-radius: 6px;
8
    border: none;
9
    cursor: pointer;
10
    font-size: 0.8rem;
11
}
12

13
.copy-css:hover {
14
 background-color: #dcdcdc;
15
}
16
.css-output {
17
  opacity: 0;
18
  }

Generating Typographic Scales with JavaScript

We’ll start by getting the input and select elements. 

1
const baseSize = document.getElementById("base-size");
2
const fontFamily = document.getElementById("font-family");
3
const fontWeight = document.getElementById("font-weight");
4
const scaleRatio = document.getElementById("scale-ratio");

We’ll also get the preview container and the Copy CSS button:

1
const preview = document.getElementById("preview");
2
const copyCSS = document.getElementById("copy-css");

Create an array of the most popular fonts and set them as options in the font family select input. Add the array as shown below.

1
 const googleFonts = [
2
        "Inter",
3
        "Roboto",
4
        "Open Sans",
5
        "Lato",
6
        "Montserrat",
7
        "Poppins",
8
        "Source Sans Pro",
9
        "Raleway",
10
        "Playfair Display",
11
        "Merriweather",
12
        "Ubuntu",
13
        "Nunito",
14
        "DM Sans",
15
        "Work Sans",
16
        "Titillium Web",
17
        "Fira Sans",
18
        "Rubik",
19
        "Lora",
20
        "Barlow",
21
        "Hind",
22
        "Cabin",
23
        "IBM Plex Sans",
24
        "Quicksand",
25
        "Karla",
26
        "PT Sans",
27
        "Heebo",
28
        "Mulish",
29
        "Overpass",
30
        "Jost",
31
        "Manrope",
32
        "Spectral",
33
        "Space Grotesk",
34
        "DM Mono",
35
        "Courier Prime",
36
        "Inconsolata",
37
      ];

Let’s populate the font family select input with our fonts array.

1
  function populateFonts() {
2
    googleFonts.forEach((font) => {
3
      const option = document.createElement("option");
4
      option.value = font;
5
      option.textContent = font;
6
      fontFamily.appendChild(option);
7
    });
8
  }
9

10
  populateFonts();

Here we are looping through the fonts array, creating an option elements for each font and setting its value and text content to the font name. Finally the option element is added to the font family select element.

Set the first font in the array as the default on the input.

1
applyFont(googleFonts[0]);

To ensure the correct font and all its weights are loaded directly from Google Fonts, create a function called applyFont() and add the currently selected font as a stylesheet link in the page header. 

1
function applyFont(font) {
2
    const existingLink = document.querySelector(
3
      "link[href*='fonts.googleapis.com']"
4
    );
5
    if (existingLink) {
6
      existingLink.remove();
7
    }
8
    const link = document.createElement("link");
9
    link.href = `https://fonts.googleapis.com/css2?family=${font}:wght@100;200;300;400;500;600;700;800;900&display=swap`;
10

11
    link.rel = "stylesheet";
12
    document.head.appendChild(link);
13
  }

Levels in typographic scales

In typographic scale systems, levels are used to define the different steps or sizes within the scale. Each level corresponds to a specific role in web design.

For example:

  • Higher levels are used for headings, for example, h1 and h2 and so on
  • The base level is mostly used for the body
  • Lower levels are mostly used for captions, foot notes, etc. 

Each higher level is calculated by multiplying the base size by the scale ratio.

A scale ratio determines how each level increases relative to the base. Common scale ratios include:

  • 1.25 (Minor Third)
  • 1.33 (Perfect Fourth)
  • 1.414 (Augmented Fourth)
  • 1.5 (Perfect Fifth)
  • 1.618 (Golden Ratio)

For example, suppose you want to use a scale ratio of 1.25 and  your base font is 16px:

  • Level 1 will be 16px * 1.25 = 20px
  • Level 2 will be 20px * 1.25  =  25px and so on.

For levels below the base, we use negative level numbers (i.e. Level -1,  Level -2, etc.  ) .These are calculated by dividing the base size by the scale ratio.

For example, keeping your base size at 16px, if you want 2 levels below the base, it will look like this:

  • Level-1 = 16px / 1.25 = 12.8px
  • Level-2 = 12.8 /1.25 = 10.24px

The levels array

Now that we have understood how to use levels and scale ratios to generate fonts, let’s define our levels array.

1
const FONT_SIZES = [
2
    { name: "h1", level: 5 },
3
    { name: "h2", level: 4 },
4
    { name: "h3", level: 3 },
5
    { name: "h4", level: 2 },
6
    { name: "h5", level: 1 },
7
    { name: "body", level: 0 },
8
    { name: "small", level: -1 },
9
  ];

Create a function called calculateSize() which will calculate the font size based on the base size, the selected scale ratio, and the expected level.

Here is the formula:

1
size = baseSize * (scaleRatio ^ level)

where :

  • baseSize is the starting font size
  • scaleRatio is the multiplier scale
  • level represents the step in the scale

The function will look like this:

1
function calculateSize(baseSize, level) {
2
    return parseFloat(
3
      (baseSize * Math.pow(scaleRatio.value, level)).toFixed(2)
4
    );
5
  }

Then, create another function which will return font sizes in rems :

1
 function calculateSizeInRem(baseSize, level) {
2
        return (calculateSize(baseSize, level) / 16).toFixed(2) + "rem";
3
      }

Now we need to update the preview section with sample text showing how each level looks. 

Updating the Preview pane

For each sample text, we will do the following:

  • Display the font size both in px and rem
  • Show a sample text that uses the currently selected size, font family, and font weight.

Here is the function that does that.

1
function updatePreview() {
2
    preview.innerHTML = "";
3
    const base = parseFloat(baseSize.value);
4
    const font = fontFamily.value;
5

6
    const weight = fontWeight.value;
7

8
    FONT_SIZES.forEach(({ name, level }) => {
9
      const size = calculateSize(base, level);
10
      const remSize = calculateSizeInRem(base, level);
11
      const item = document.createElement("div");
12
      item.classList.add("scale-item");
13

14
      const pxLabel = document.createElement("div");
15
      const remLabel = document.createElement("div");
16
      remLabel.textContent = `${remSize}`;
17

18
      pxLabel.textContent = `${size}px`;
19
      pxLabel.classList.add("scale-label");
20
      remLabel.classList.add("scale-label");
21

22
      const text = document.createElement("p");
23

24
      text.style.fontSize = `${size}px`;
25
      text.style.fontFamily = font + ", sans-serif";
26
      text.style.fontWeight = weight;
27

28
      text.style.lineHeight = level >= 0 ? "1.15" : "1.65";
29
      text.textContent =
30
        "Every project has its own distinct requirements. ";
31

32
      item.appendChild(remLabel);
33
      item.appendChild(pxLabel);
34
      item.appendChild(text);
35

36
      preview.appendChild(item);
37
    });
38
  }

Let’s break down the code.

First, we clear the preview container to ensure the previous sample text is removed before a new sample is rendered.

1
 preview.innerHTML = "";

Next, we get the values from the inputs.

  • baseSize.value – The current base font size in pixels
  • fontFamily.value – The selected font family from the dropdown.
  • fontWeight.value –  The chosen font-weight 

Then we loop over the FONT_SIZES array and iterate over each typography item. For each item,  calculate the font size based on the selected scaleRatio and current baseSize.

1
 FONT_SIZES.forEach(({ name, level }) => {
2
 
3
 }

Then we create preview elements for each size. Each item will have :

  • A container for the scale item
  • 2 labels showing  the size in px and rem
  • A paragraph to display the sample text

Here, we applied the predefined styles to the elements.

1
const item = document.createElement("div");
2
item.classList.add("scale-item");
3
const pxLabel = document.createElement("div");
4
const remLabel = document.createElement("div");
5
remLabel.textContent = `${remSize}`;
6
pxLabel.textContent = `${size}px`;
7
pxLabel.classList.add("scale-label");
8
remLabel.classList.add("scale-label");
9
const text = document.createElement("p");

Here we applied the generated text sizes to the preview.

1
text.style.fontSize = `${size}px`;
2
text.style.fontFamily = font + ", sans-serif";
3
text.style.fontWeight = weight;
4
text.style.lineHeight = level >= 0 ? "1.15" : "1.65";
5
text.textContent = "Every project has its own distinct requirements.";

Finally, we append remLabel, pxLabel, and the preview text to each scale item container and add it to the preview section.

1
item.appendChild(remLabel);
2
item.appendChild(pxLabel);
3
item.appendChild(text);
4
preview.appendChild(item);
5
updatePreview();

Invoke the updatePreview() function so the changes are effected .

Whenever you change any value such as the base, scale ratio, or weight, these changes should be updated in real-time. This is done by adding event listeners to each input so that any change automatically triggers the updatePreview() function 

1
baseSize.addEventListener("input", updatePreview);
2
fontFamily.addEventListener("change", updatePreview);
3
scaleRatio.addEventListener("change", updatePreview);
4
fontWeight.addEventListener("input", updatePreview);

Generate CSS Variables

The last feature is the ability to automatically generate CSS variables for the calculated font sizes. This makes it easy to copy and use them in your projects.

The final format of the CSS variables will look like this:

1
:root { 
2

3
   --font-size-h1: 48.83px;
4
  --font-size-h2: 39.06px;
5
  --font-size-h3: 31.25px;
6
  --font-size-h4: 25px;
7
  --font-size-h5: 20px;
8
  --font-size-body: 16px;
9
  --font-size-small: 12.8px;
10
}
11


To achieve this format, we will build a css string that begins with the opening of a :root block. The :root is a pseudo-class selector commonly used to define global CSS variables that can be used throughout the entire stylesheet.

Let’s build the string:

1
let css = `:root { \n\n `;

Get the current values for the base size and scale ratios from the inputs.

1
const base = parseFloat(baseSize.value) || 16;
2
const SCALE_RATIO = parseFloat(scaleRatio.value);

Create a helper function called poweredBy()  which will calculate the font sizes. .

1
function poweredBy(base, scale, level) {
2
  return parseFloat((base * Math.pow(scale, level)).toFixed(2));
3
}

Create an object called fontSizes for holding the sizes for different levels

1
const fontSizes = {
2
  h1: poweredBy(base, SCALE_RATIO, 5),
3
  h2: poweredBy(base, SCALE_RATIO, 4),
4
  h3: poweredBy(base, SCALE_RATIO, 3),
5
  h4: poweredBy(base, SCALE_RATIO, 2),
6
  h5: poweredBy(base, SCALE_RATIO, 1),
7
  body: poweredBy(base, SCALE_RATIO, 0),
8
  small: poweredBy(base, SCALE_RATIO, -1),
9
};

Now, add each calculated value as a CSS variable to the css string and close the :root block.

1
css += `  --font-size-heading1: ${fontSizes.h1}px;\n`;
2
css += `  --font-size-heading2: ${fontSizes.h2}px;\n`;
3
css += `  --font-size-heading3: ${fontSizes.h3}px;\n`;
4
css += `  --font-size-heading4: ${fontSizes.h4}px;\n`;
5
css += `  --font-size-heading5: ${fontSizes.h5}px;\n`;
6
css += `  --font-size-body: ${fontSizes.body}px;\n`;
7
css += `  --font-size-small: ${fontSizes.small}px;\n`;
8
css += `}\n\n`;

Finally, add the generated CSS string to the css output element to ensure it’s available for easy copying to the clipboard.

1
document.getElementById("css-output").textContent = css;
2
        

Copy Generated CSS

Copying text to a clipboard on a web page is done using the navigator.clipboard.writeText() method which will look like this:

1
function copyToClipboard() {
2
    const cssText = generateCSS();
3
    navigator.clipboard.writeText(cssText).then(() => {
4
      alert("CSS copied to clipboard!");
5
    });
6
  }

We also need to ensure the copyCSS() function is attached to the click event of the copy CSS button. Additionally, it’s important to ensure the default CSS values are generated after the DOM is fully loaded.

1
copyCSS.addEventListener("click", copyToClipboard);
2
document.addEventListener("DOMContentLoaded", generateCSS);

Here is the final demo:

Conclusion

That’s a wrap for the typograhic scale generator! You can build on this by customizing it further–for example, instead of using a paragraph for the preview, you can add a card or have a hero section that changes based on the generated typescale values.



Source link

Build JavaScript Scale tool Typographic
Share. Facebook Twitter Pinterest LinkedIn Tumblr WhatsApp Email
Previous ArticleManychat Birthday in Barcelona: A Lone Wolf Builds Connection
Next Article Daily Search Forum Recap: July 1, 2025
admin
  • Website

Related Posts

A Practical Guide To Building With Clarity (Part 2) — Smashing Magazine

October 3, 2025

Fresh Resources for Web Designers and Developers (September 2025)

October 2, 2025

Shades Of October (2025 Wallpapers Edition) — Smashing Magazine

October 1, 2025

Principles And Implementation (Part 1) — Smashing Magazine

September 29, 2025
Leave A Reply Cancel Reply

  • Facebook
  • Twitter
  • Pinterest
  • Instagram
  • YouTube
  • Vimeo
Don't Miss
Marketing

Driving Qualified Leads With LinkedIn Content: A Proven Formula

By adminOctober 3, 20250

Are you struggling to generate qualified leads from your LinkedIn content? Wondering how to transform…

Google Ads copywriting with AI: Getting the prompt right

October 3, 2025

A Practical Guide To Building With Clarity (Part 2) — Smashing Magazine

October 3, 2025

Meta unveils Business AI and new generative tools

October 2, 2025

Subscribe to Updates

Get the latest creative news from Trendswave about Marketing, SEO & Web Design.

Please enable JavaScript in your browser to complete this form.
Loading
About Us

Trendswave is an Influencer Marketing Agency with access to one of the largest influencer networks in the Poland, connecting brands and agencies to only the best influencers and social media thought leaders.

Our Picks

Driving Qualified Leads With LinkedIn Content: A Proven Formula

October 3, 2025

Google Ads copywriting with AI: Getting the prompt right

October 3, 2025
Quicklinks
  • Influencer Marketing
  • Marketing
  • SEO
  • Social Media
  • Web Design
  • About Us
  • Contact Us
  • Disclaimer
  • Privacy Policy
  • Terms and Conditions
© 2025 Trendswave.All Rights Reserved

Type above and press Enter to search. Press Esc to cancel.