Skip to Content
Veltix
ThemesTypography

Typography

Veltix provides comprehensive typography management with flexible font systems and responsive text scaling.

Overview

Typography features include:

  • Font Families: Multiple font stack options
  • Font Sizes: Responsive size scales
  • Font Weights: Complete weight ranges
  • Line Heights: Optimized spacing
  • Text Utilities: Ready-to-use text styles

Font Families

Default Font Stacks

// Veltix default font families const fontFamilies = { sans: [ 'Inter', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'sans-serif' ], serif: [ 'Georgia', 'Cambria', 'Times New Roman', 'Times', 'serif' ], mono: [ 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Source Code Pro', 'Menlo', 'Consolas', 'DejaVu Sans Mono', 'monospace' ], display: [ 'Poppins', 'Inter', 'system-ui', 'sans-serif' ] };

Custom Font Configuration

// Custom font configuration const customFonts = { brand: { name: 'Brand Font', family: ['BrandFont', 'Inter', 'sans-serif'], weights: [300, 400, 500, 600, 700], styles: ['normal', 'italic'] }, heading: { name: 'Heading Font', family: ['HeadingFont', 'Poppins', 'sans-serif'], weights: [400, 500, 600, 700, 800], styles: ['normal'] }, body: { name: 'Body Font', family: ['BodyFont', 'Inter', 'sans-serif'], weights: [300, 400, 500], styles: ['normal', 'italic'] } }; // Font loading utility const loadFonts = async (fonts) => { const fontPromises = fonts.map(font => { return new FontFace(font.name, `url(${font.url})`).load(); }); const loadedFonts = await Promise.all(fontPromises); loadedFonts.forEach(font => document.fonts.add(font)); return loadedFonts; };

Font Sizes

Responsive Size Scale

// Responsive font size scale const fontSizes = { xs: { base: '0.75rem', // 12px sm: '0.875rem', // 14px lg: '1rem' // 16px }, sm: { base: '0.875rem', // 14px sm: '1rem', // 16px lg: '1.125rem' // 18px }, base: { base: '1rem', // 16px sm: '1.125rem', // 18px lg: '1.25rem' // 20px }, lg: { base: '1.125rem', // 18px sm: '1.25rem', // 20px lg: '1.5rem' // 24px }, xl: { base: '1.25rem', // 20px sm: '1.5rem', // 24px lg: '1.875rem' // 30px }, '2xl': { base: '1.5rem', // 24px sm: '1.875rem', // 30px lg: '2.25rem' // 36px }, '3xl': { base: '1.875rem', // 30px sm: '2.25rem', // 36px lg: '3rem' // 48px }, '4xl': { base: '2.25rem', // 36px sm: '3rem', // 48px lg: '4rem' // 64px }, '5xl': { base: '3rem', // 48px sm: '4rem', // 64px lg: '5rem' // 80px } };

Fluid Typography

// Fluid typography utility const createFluidTypography = (minSize, maxSize, minWidth = 320, maxWidth = 1200) => { const minSizeRem = minSize / 16; const maxSizeRem = maxSize / 16; const minWidthRem = minWidth / 16; const maxWidthRem = maxWidth / 16; const slope = (maxSizeRem - minSizeRem) / (maxWidthRem - minWidthRem); const intercept = minSizeRem - slope * minWidthRem; return `clamp(${minSizeRem}rem, ${intercept}rem + ${slope * 100}vw, ${maxSizeRem}rem)`; }; // Fluid typography examples const fluidTypography = { h1: createFluidTypography(32, 64), h2: createFluidTypography(24, 48), h3: createFluidTypography(20, 36), h4: createFluidTypography(18, 30), h5: createFluidTypography(16, 24), h6: createFluidTypography(14, 20), body: createFluidTypography(14, 18), small: createFluidTypography(12, 14) };

Font Weights

Weight Scale

// Font weight scale const fontWeights = { thin: 100, extralight: 200, light: 300, normal: 400, medium: 500, semibold: 600, bold: 700, extrabold: 800, black: 900 }; // Weight utilities const weightUtils = { // Get weight value getWeight: (weight) => fontWeights[weight] || weight, // Check if weight is available for font isWeightAvailable: (fontFamily, weight) => { const weights = getAvailableWeights(fontFamily); return weights.includes(weight); }, // Get available weights for font getAvailableWeights: (fontFamily) => { // This would typically check the loaded font return [300, 400, 500, 600, 700]; } };

Line Heights

Optimized Line Heights

// Line height scale const lineHeights = { none: 1, tight: 1.25, snug: 1.375, normal: 1.5, relaxed: 1.625, loose: 2 }; // Responsive line heights const responsiveLineHeights = { xs: { base: 1.25, sm: 1.375, lg: 1.5 }, sm: { base: 1.375, sm: 1.5, lg: 1.625 }, base: { base: 1.5, sm: 1.625, lg: 1.75 }, lg: { base: 1.625, sm: 1.75, lg: 1.875 }, xl: { base: 1.75, sm: 1.875, lg: 2 } }; // Calculate optimal line height const calculateLineHeight = (fontSize, lineHeight = 'normal') => { const size = typeof fontSize === 'string' ? parseInt(fontSize) : fontSize; const baseLineHeight = lineHeights[lineHeight] || lineHeight; return size * baseLineHeight; };

Text Utilities

Typography Components

// Typography component function Typography({ variant = 'body', size = 'base', weight = 'normal', family = 'sans', color = 'inherit', align = 'left', children, ...props }) { const typographyStyles = { fontFamily: fontFamilies[family].join(', '), fontSize: fontSizes[size].base, fontWeight: fontWeights[weight], lineHeight: responsiveLineHeights[size].base, color, textAlign: align, ...getVariantStyles(variant) }; return ( <div style={typographyStyles} {...props}> {children} </div> ); } // Variant styles const getVariantStyles = (variant) => { const variants = { h1: { fontSize: fontSizes['4xl'].base, fontWeight: fontWeights.bold, lineHeight: lineHeights.tight }, h2: { fontSize: fontSizes['3xl'].base, fontWeight: fontWeights.semibold, lineHeight: lineHeights.snug }, h3: { fontSize: fontSizes['2xl'].base, fontWeight: fontWeights.semibold, lineHeight: lineHeights.snug }, h4: { fontSize: fontSizes.xl.base, fontWeight: fontWeights.medium, lineHeight: lineHeights.normal }, h5: { fontSize: fontSizes.lg.base, fontWeight: fontWeights.medium, lineHeight: lineHeights.normal }, h6: { fontSize: fontSizes.base.base, fontWeight: fontWeights.medium, lineHeight: lineHeights.normal }, body: { fontSize: fontSizes.base.base, fontWeight: fontWeights.normal, lineHeight: lineHeights.relaxed }, small: { fontSize: fontSizes.sm.base, fontWeight: fontWeights.normal, lineHeight: lineHeights.normal }, caption: { fontSize: fontSizes.xs.base, fontWeight: fontWeights.normal, lineHeight: lineHeights.normal } }; return variants[variant] || variants.body; };

Text Utilities Hook

// Typography utilities hook const useTypography = () => { const getFontSize = useCallback((size, responsive = false) => { if (responsive) { return fontSizes[size]; } return fontSizes[size].base; }, []); const getLineHeight = useCallback((size, responsive = false) => { if (responsive) { return responsiveLineHeights[size]; } return responsiveLineHeights[size].base; }, []); const getFontWeight = useCallback((weight) => { return fontWeights[weight] || weight; }, []); const getFontFamily = useCallback((family) => { return fontFamilies[family].join(', '); }, []); const createTextStyle = useCallback(({ size = 'base', weight = 'normal', family = 'sans', lineHeight = 'normal', color = 'inherit' }) => { return { fontSize: getFontSize(size), fontWeight: getFontWeight(weight), fontFamily: getFontFamily(family), lineHeight: lineHeights[lineHeight], color }; }, [getFontSize, getFontWeight, getFontFamily]); return { getFontSize, getLineHeight, getFontWeight, getFontFamily, createTextStyle }; };

Responsive Typography

Breakpoint-based Typography

// Responsive typography system const responsiveTypography = { h1: { xs: { fontSize: '1.5rem', lineHeight: 1.25 }, sm: { fontSize: '2rem', lineHeight: 1.25 }, md: { fontSize: '2.5rem', lineHeight: 1.2 }, lg: { fontSize: '3rem', lineHeight: 1.2 }, xl: { fontSize: '3.5rem', lineHeight: 1.1 } }, h2: { xs: { fontSize: '1.25rem', lineHeight: 1.3 }, sm: { fontSize: '1.5rem', lineHeight: 1.3 }, md: { fontSize: '1.875rem', lineHeight: 1.25 }, lg: { fontSize: '2.25rem', lineHeight: 1.25 }, xl: { fontSize: '2.5rem', lineHeight: 1.2 } }, body: { xs: { fontSize: '0.875rem', lineHeight: 1.5 }, sm: { fontSize: '1rem', lineHeight: 1.5 }, md: { fontSize: '1.125rem', lineHeight: 1.6 }, lg: { fontSize: '1.25rem', lineHeight: 1.6 }, xl: { fontSize: '1.375rem', lineHeight: 1.6 } } }; // Responsive text component function ResponsiveText({ variant = 'body', breakpoint = 'md', children, ...props }) { const styles = responsiveTypography[variant][breakpoint]; return ( <div style={styles} {...props}> {children} </div> ); }

CSS-in-JS Responsive Typography

// CSS-in-JS responsive typography const createResponsiveTypography = (variant) => { const styles = responsiveTypography[variant]; return ` font-size: ${styles.xs.fontSize}; line-height: ${styles.xs.lineHeight}; @media (min-width: 640px) { font-size: ${styles.sm.fontSize}; line-height: ${styles.sm.lineHeight}; } @media (min-width: 768px) { font-size: ${styles.md.fontSize}; line-height: ${styles.md.lineHeight}; } @media (min-width: 1024px) { font-size: ${styles.lg.fontSize}; line-height: ${styles.lg.lineHeight}; } @media (min-width: 1280px) { font-size: ${styles.xl.fontSize}; line-height: ${styles.xl.lineHeight}; } `; };

Typography Themes

Theme-based Typography

// Typography theme configuration const typographyTheme = { fonts: { primary: fontFamilies.sans, secondary: fontFamilies.serif, mono: fontFamilies.mono, display: fontFamilies.display }, sizes: { xs: '0.75rem', sm: '0.875rem', base: '1rem', lg: '1.125rem', xl: '1.25rem', '2xl': '1.5rem', '3xl': '1.875rem', '4xl': '2.25rem', '5xl': '3rem' }, weights: { light: 300, normal: 400, medium: 500, semibold: 600, bold: 700, extrabold: 800 }, lineHeights: { none: 1, tight: 1.25, snug: 1.375, normal: 1.5, relaxed: 1.625, loose: 2 }, letterSpacing: { tighter: '-0.05em', tight: '-0.025em', normal: '0em', wide: '0.025em', wider: '0.05em', widest: '0.1em' } }; // Apply typography theme const applyTypographyTheme = (theme) => { const root = document.documentElement; // Apply font families Object.entries(theme.fonts).forEach(([name, family]) => { root.style.setProperty(`--font-family-${name}`, family.join(', ')); }); // Apply font sizes Object.entries(theme.sizes).forEach(([size, value]) => { root.style.setProperty(`--font-size-${size}`, value); }); // Apply font weights Object.entries(theme.weights).forEach(([weight, value]) => { root.style.setProperty(`--font-weight-${weight}`, value); }); // Apply line heights Object.entries(theme.lineHeights).forEach(([height, value]) => { root.style.setProperty(`--line-height-${height}`, value); }); // Apply letter spacing Object.entries(theme.letterSpacing).forEach(([spacing, value]) => { root.style.setProperty(`--letter-spacing-${spacing}`, value); }); };

Performance Optimization

Font Loading Optimization

// Font loading optimization const optimizeFontLoading = (fonts) => { // Preload critical fonts const criticalFonts = fonts.filter(font => font.critical); criticalFonts.forEach(font => { const link = document.createElement('link'); link.rel = 'preload'; link.as = 'font'; link.href = font.url; link.crossOrigin = 'anonymous'; document.head.appendChild(link); }); // Load non-critical fonts with lower priority const nonCriticalFonts = fonts.filter(font => !font.critical); nonCriticalFonts.forEach(font => { const link = document.createElement('link'); link.rel = 'preload'; link.as = 'font'; link.href = font.url; link.crossOrigin = 'anonymous'; link.media = 'print'; link.onload = () => { link.media = 'all'; }; document.head.appendChild(link); }); }; // Font display optimization const fontDisplayOptions = { auto: 'auto', block: 'block', swap: 'swap', fallback: 'fallback', optional: 'optional' }; // Optimize font display const optimizeFontDisplay = (fontFamily, display = 'swap') => { const style = document.createElement('style'); style.textContent = ` @font-face { font-family: '${fontFamily}'; font-display: ${display}; } `; document.head.appendChild(style); };

Best Practices

1. Font Selection

  • Choose fonts that match your brand
  • Consider readability and accessibility
  • Test fonts across different devices
  • Optimize font loading performance

2. Size and Spacing

  • Use consistent size scales
  • Ensure sufficient contrast
  • Optimize line heights for readability
  • Test typography at different screen sizes

3. Performance

  • Optimize font loading
  • Use font-display: swap
  • Minimize font file sizes
  • Cache font resources

4. Accessibility

  • Ensure sufficient color contrast
  • Use appropriate font sizes
  • Provide alternative fonts
  • Test with screen readers

Troubleshooting

Common Issues

Fonts not loading

  • Check font URLs and paths
  • Verify CORS settings
  • Test font loading performance
  • Check browser compatibility

Typography inconsistencies

  • Verify font family fallbacks
  • Check font weight availability
  • Test across different browsers
  • Validate CSS specificity

Performance issues

  • Optimize font loading
  • Use font-display strategies
  • Minimize font file sizes
  • Implement proper caching
Last updated on