
Type Scale
- 10 installs
- 37 repo stars
- Updated December 30, 2025
- dylantarre/design-system-skills
Generates typography scales using modular ratios with auto-calculated line heights for heading hierarchy, output as CSS, Tailwind, or JSON.
About
This skill generates typography scales using modular ratios with auto-calculated line heights. A developer uses it to set up font-size tokens and heading hierarchy.
- Modular-ratio type scale
- Auto-calculated line heights
Type Scale by the numbers
- 10 all-time installs (skills.sh)
- Ranked #1,450 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dylantarre/design-system-skills --skill type-scaleAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 10 |
|---|---|
| repo stars | ★ 37 |
| Last updated | December 30, 2025 |
| Repository | dylantarre/design-system-skills ↗ |
What it does
Generates typography scales using modular ratios with auto-calculated line heights for heading hierarchy, output as CSS, Tailwind, or JSON.
Files
Type Scale Generator
Overview
Generate harmonious typography scales using musical interval ratios. Automatically calculates appropriate line heights based on font size for optimal readability.
When to Use
- Setting up typography for a new project
- Creating heading hierarchy (h1-h6)
- Standardizing font sizes across components
- Building a responsive type system
Quick Reference: Musical Ratios
| Name | Ratio | Character |
|---|---|---|
| Minor Second | 1.067 | Subtle, tight |
| Major Second | 1.125 | Conservative |
| Minor Third | 1.2 | Versatile (recommended) |
| Major Third | 1.25 | Balanced |
| Perfect Fourth | 1.333 | Bold contrast |
| Augmented Fourth | 1.414 | Dramatic |
| Perfect Fifth | 1.5 | High contrast |
| Golden Ratio | 1.618 | Classical, striking |
The Process
1. Get base size: Default 16px (browser default, good baseline) 2. Choose ratio: Recommend Minor Third (1.2) for most projects 3. Steps up: How many sizes above base (6-8 typical for headings) 4. Steps down: How many sizes below base (2-3 for small/caption text) 5. Ask unit: px, rem, or em? 6. Ask format: CSS, Tailwind, or JSON? 7. Generate: Create scale with auto line heights
Auto Line Height
Larger fonts need tighter line height for readability:
| Font Size | Line Height | Reasoning |
|---|---|---|
| 14px or less | 1.7 | Small text needs room |
| 15-18px | 1.6 | Body text range |
| 19-24px | 1.5 | Large body/small headings |
| 25-32px | 1.4 | Subheadings |
| 33-48px | 1.3 | Headings |
| 49px+ | 1.2 | Display text |
Output Formats
CSS Custom Properties:
:root {
/* Font Sizes */
--text-xs: 13.33px;
--text-sm: 14.22px;
--text-base: 16px;
--text-lg: 19.2px;
--text-xl: 23.04px;
--text-2xl: 27.65px;
/* Line Heights */
--leading-xs: 1.70;
--leading-sm: 1.70;
--leading-base: 1.60;
--leading-lg: 1.50;
--leading-xl: 1.50;
--leading-2xl: 1.40;
}Tailwind Config:
module.exports = {
theme: {
fontSize: {
'xs': ['13.33px', { lineHeight: '1.70' }],
'sm': ['14.22px', { lineHeight: '1.70' }],
'base': ['16px', { lineHeight: '1.60' }],
'lg': ['19.2px', { lineHeight: '1.50' }],
'xl': ['23.04px', { lineHeight: '1.50' }],
'2xl': ['27.65px', { lineHeight: '1.40' }],
}
}
}JSON Tokens:
{
"typography": {
"xs": { "fontSize": "13.33px", "lineHeight": "1.70" },
"sm": { "fontSize": "14.22px", "lineHeight": "1.70" },
"base": { "fontSize": "16px", "lineHeight": "1.60" },
"lg": { "fontSize": "19.2px", "lineHeight": "1.50" }
}
}Naming Convention
| Position | Name |
|---|---|
| 3 below base | xxs |
| 2 below base | xs |
| 1 below base | sm |
| Base | base |
| 1 above base | lg |
| 2 above base | xl |
| 3+ above base | 2xl, 3xl, 4xl... |
Common Configurations
Compact UI (dashboards, data-dense):
- Ratio: 1.125 (Major Second)
- Base: 14px
- Steps: 2 down, 5 up
Content Site (blogs, marketing):
- Ratio: 1.25 (Major Third)
- Base: 18px
- Steps: 2 down, 6 up
Editorial (magazines, long-form):
- Ratio: 1.333 (Perfect Fourth)
- Base: 20px
- Steps: 2 down, 8 up
/**
* Type Scale Generation Algorithm
*
* Generates typography scales using musical interval ratios.
* Includes automatic line-height calculation based on font size.
*
* Usage:
* const tokens = generateTypeScale(16, 1.25, 6, 2, 'px');
*/
type UnitType = 'px' | 'rem' | 'em';
interface TypeToken {
name: string;
size: number;
formatted: string;
lineHeight: string;
}
/** Musical interval ratios - the foundation of harmonious type scales */
const SCALE_PRESETS = [
{ name: 'Minor Second', ratio: 1.067 },
{ name: 'Major Second', ratio: 1.125 },
{ name: 'Minor Third', ratio: 1.2 },
{ name: 'Major Third', ratio: 1.25 },
{ name: 'Perfect Fourth', ratio: 1.333 },
{ name: 'Augmented Fourth', ratio: 1.414 },
{ name: 'Perfect Fifth', ratio: 1.5 },
{ name: 'Golden Ratio', ratio: 1.618 },
];
/** Names for sizes below base */
const TYPE_NAMES_DOWN = ['xxs', 'xs', 'sm'];
/** Names for sizes above base */
const TYPE_NAMES_UP = ['lg', 'xl', '2xl', '3xl', '4xl', '5xl', '6xl', '7xl', '8xl', '9xl'];
/**
* Calculate optimal line height based on font size.
* Larger fonts need tighter line height for readability.
*/
function calculateLineHeight(fontSize: number): number {
if (fontSize <= 14) return 1.7;
if (fontSize <= 18) return 1.6;
if (fontSize <= 24) return 1.5;
if (fontSize <= 32) return 1.4;
if (fontSize <= 48) return 1.3;
return 1.2;
}
/**
* Generate a typography scale.
*
* @param baseSize - The base font size (typically 16px)
* @param ratio - Scale ratio (e.g., 1.25 for Major Third)
* @param stepsUp - Number of sizes above base (for headings)
* @param stepsDown - Number of sizes below base (for small text)
* @param unit - Output unit: 'px', 'rem', or 'em'
*
* The algorithm:
* size = baseSize * (ratio ^ step)
*
* Steps above base use positive exponents, below use negative.
*/
function generateTypeScale(
baseSize: number,
ratio: number,
stepsUp: number,
stepsDown: number,
unit: UnitType
): TypeToken[] {
const tokens: TypeToken[] = [];
// Generate steps below base (smallest first)
for (let i = stepsDown; i > 0; i--) {
const size = baseSize / Math.pow(ratio, i);
const roundedSize = Math.round(size * 100) / 100;
const lineHeight = calculateLineHeight(roundedSize);
const nameIndex = 3 - i; // Map to xxs, xs, sm
const name = TYPE_NAMES_DOWN[nameIndex] || `down-${i}`;
tokens.push({
name,
size: roundedSize,
formatted: `${roundedSize}${unit}`,
lineHeight: lineHeight.toFixed(2),
});
}
// Base size
const baseLineHeight = calculateLineHeight(baseSize);
tokens.push({
name: 'base',
size: baseSize,
formatted: `${baseSize}${unit}`,
lineHeight: baseLineHeight.toFixed(2),
});
// Generate steps above base
for (let i = 1; i <= stepsUp; i++) {
const size = baseSize * Math.pow(ratio, i);
const roundedSize = Math.round(size * 100) / 100;
const lineHeight = calculateLineHeight(roundedSize);
const name = TYPE_NAMES_UP[i - 1] || `${i + 1}xl`;
tokens.push({
name,
size: roundedSize,
formatted: `${roundedSize}${unit}`,
lineHeight: lineHeight.toFixed(2),
});
}
return tokens;
}
// ============================================================================
// Output Formatting
// ============================================================================
/** Generate CSS custom properties */
function generateCSS(tokens: TypeToken[], prefix = 'text'): string {
let css = ':root {\n';
css += ' /* Font Sizes */\n';
tokens.forEach((token) => {
css += ` --${prefix}-${token.name}: ${token.formatted};\n`;
});
css += '\n /* Line Heights */\n';
tokens.forEach((token) => {
css += ` --leading-${token.name}: ${token.lineHeight};\n`;
});
css += '}\n';
return css;
}
/** Generate Tailwind config */
function generateTailwind(tokens: TypeToken[]): string {
let config = 'module.exports = {\n theme: {\n fontSize: {\n';
tokens.forEach((token) => {
config += ` '${token.name}': ['${token.formatted}', { lineHeight: '${token.lineHeight}' }],\n`;
});
config += ' }\n }\n}\n';
return config;
}
/** Generate JSON tokens */
function generateJSON(tokens: TypeToken[], prefix = 'text'): string {
const obj: Record<string, { fontSize: string; lineHeight: string }> = {};
tokens.forEach((token) => {
obj[`${prefix}-${token.name}`] = {
fontSize: token.formatted,
lineHeight: token.lineHeight,
};
});
return JSON.stringify({ typography: obj }, null, 2);
}
export {
generateTypeScale,
calculateLineHeight,
generateCSS,
generateTailwind,
generateJSON,
SCALE_PRESETS,
TYPE_NAMES_DOWN,
TYPE_NAMES_UP,
type TypeToken,
type UnitType,
};