Tailwind CSS Font Variant Numeric
Font Variant Numeric is a CSS property for styling numeric typograpy. It can profoundly influence the readability and style of a design, especially in contexts like financial documents, data tables, or any interface involving numerical data. It controls how numeric text is displayed, including options like proportional or tabular figures, slashed zeros, fractions, etc.
Tailwind CSS provides an extensive suite of utilities for managing font-variant-numeric
styles. In this guide, we will dive deep into the utilities offered by Tailwind CSS for using Font Variant Numeric.
Class | Properties | Example |
---|---|---|
normal-nums | font-variant-numeric: normal; | <div className="normal-nums"></div> |
ordinal | font-variant-numeric: ordinal; | <div className="ordinal"></div> |
slashed-zero | font-variant-numeric: slashed-zero; | <div className="slashed-zero"></div> |
lining-nums | font-variant-numeric: lining-nums; | <div className="lining-nums"></div> |
oldstyle-nums | font-variant-numeric: oldstyle-nums; | <div className="oldstyle-nums"></div> |
proportional-nums | font-variant-numeric: proportional-nums; | <div className="proportional-nums"></div> |
tabular-nums | font-variant-numeric: tabular-nums; | <div className="tabular-nums"></div> |
diagonal-fractions | font-variant-numeric: diagonal-fractions; | <div className="diagonal-fractions"></div> |
stacked-fractions | font-variant-numeric: stacked-fractions; | <div className="stacked-fractions"></div> |
Overview of Font Variant Numeric
Adding the Font Variant Numeric
To apply Font Variant Numeric styles, simply add the appropriate Tailwind utility class to your element, such as ordinal
, slashed-zero
, or lining-nums
. Keep in mind that not all fonts support every numeric style, so ensure the font you’re using supports the specific style you want to apply.
Adding the Ordinal
Ordinal numbers (e.g., 1st, 2nd, 3rd) often get a typographic adjustment, elevating the letters like superscripts. Tailwind provides an ordinal
utility to enable this feature.
export default function OrdinalExample() { return ( <div className="font-sans text-xl w-screen h-screen bg-gray-200 flex items-center justify-center gap-1"> <p className="ordinal">21st</p> <span>Century</span> </div> ); }
Adding the Slashed Zero
The slashed zero style adds a diagonal slash through zeros, improving clarity in contexts involving long sequences of numerical data where 0s and Os can be confused. Tailwind implements this through the slashed-zero
utility.
export default function SlashedZeroDisplay() { return ( <div className="font-[Inter] w-screen h-screen bg-gray-50 flex items-center justify-center"> <p className="slashed-zero text-lg">Order ID: 10020</p> </div> ); }
Adding the Lining Figures
Lining figures are numeric styles where all digits have a consistent height and align neatly with uppercase letters. This is also the default style of most fonts. In Tailwind CSS, you can easily apply this style by using the lining-nums
utility.
export default function LiningFiguresExample() { return ( <div className="font-[Inter] w-screen h-screen bg-gray-300 flex items-center justify-center"> <p className="lining-nums text-lg">1234567890</p> </div> ); }
Adding the Oldstyle Figures
Oldstyle Figures are a typographic style where numbers have varying heights and alignments. Unlike lining figures, oldstyle figures feature ascenders and descenders. In Tailwind CSS, the oldstyle-nums
utility enables this style when supported by the font.
export default function OldStyleTypography() { return ( <div className="font-[Georgia] w-screen h-screen bg-gray-100 flex items-center justify-center"> <p className="oldstyle-nums text-lg">1234567890</p> </div> ); }
Adding the Proportional Figures
Proportional figures are numbers where each digit has a width that matches its design, creating a natural and visually pleasing flow when placed in running text. This style is ideal for content such as articles or paragraphs where numbers appear alongside letters, as the spacing feels more balanced. Tailwind’s proportional-nums
utility enables proportional figures, provided the font supports this feature.
export default function ProportionalFiguresExample() { return ( <div className="font-sans w-screen h-screen bg-gray-400 flex flex-col items-center justify-center text-lg"> <p className="proportional-nums"> 111111 </p> <p className="proportional-nums"> 897789 </p> </div> ); }
Adding the Tabular Figures
Tabular figures are numbers with equal width, ensuring perfect alignment across rows and columns. This makes them ideal for tabular data, financial reports, or any layout where numerical values need to align vertically. In Tailwind CSS, the tabular-nums
utility activates this style, making it easier to display structured and legible numeric content in supported fonts.
export default function TabularFiguresDisplay() { return ( <div className="font-sans w-screen h-screen bg-gray-300 flex flex-col items-center justify-center"> <p className="tabular-nums"> 111111 </p> <p className="tabular-nums"> 897789 </p> </div> ); }
Adding the Diagonal Fractions
Diagonal Fractions are a typographic style where fractions, such as ½
or ¾
, are displayed with a diagonal slash separating the numerator and denominator. This style is compact, visually appealing, and commonly used in casual or inline text, such as recipes or technical specifications. Tailwind’s diagonal-fractions
utility enables this style when supported by the font.
export default function FractionalTypography() { return ( <div className="font-sans w-screen h-screen bg-gray-200 flex items-center justify-center"> <p className="diagonal-fractions text-lg">1/2 cup sugar</p> </div> ); }
Resetting the Numeric Variants
When you need to reset numeric font variants after applying specific styles, use the normal-nums
utility. This utility can be helpful when used with state or breakpoint modifiers.
export default function ResetNumericVariants() { return ( <div className="font-[Inter] w-screen h-screen bg-gray-200 flex items-center justify-center"> <p className="normal-nums text-lg">1111111</p> </div> ); }
States and Responsiveness
Tailwind allows numeric font styles to be applied conditionally using various state and responsive modifiers.
Hover and Focus States
You can dynamically apply font-variant-numeric
styles by combining them with hover
or focus
states, e.g., hover:ordinal
, focus:ordinal
, etc.
export default function HoverFocusNumericStyle() { return ( <div className="font-sans w-screen h-screen bg-gray-200 flex flex-col gap-6 items-center justify-center text-center px-10"> <p className="underline">Hover on the below text to change the font variants</p> <p className="hover:ordinal text-lg"> 1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th </p> </div> ); }
Breakpoint Modifiers
You can also apply font-numeric-styles
based on screen size with the help of breakpoint modifiers- sm
, md
, lg
, etc.
export default function ResponsiveNumericStyling() { return ( <div className="font-sans w-screen h-screen bg-gray-200 flex flex-col gap-6 items-center justify-center text-center px-10"> <p className="underline">Ordinal utility will be active on "md" and above</p> <p className="md:ordinal text-lg"> 1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th </p> </div> ); }
Real World Examples
Financial Report Dashboard
A dashboard component displaying financial metrics with tabular numeric values using different font variant numeric styles.
export default function FinancialDashboard() { const financialData = [ { metric: "Revenue", value: "$1,234,567.89", growth: "+12.5%", period: "2023" }, { metric: "Operating Cost", value: "$876,543.21", growth: "-5.2%", period: "2023" }, { metric: "Net Profit", value: "$358,024.68", growth: "+18.7%", period: "2023" }, { metric: "Cash Flow", value: "$456,789.12", growth: "+8.9%", period: "2023" }, { metric: "Assets", value: "$2,987,654.32", growth: "+15.3%", period: "2023" }, { metric: "Liabilities", value: "$1,543,210.98", growth: "-3.4%", period: "2023" } ]; return ( <div className="p-6 bg-gray-50"> <h2 className="text-2xl font-bold mb-6">Financial Overview</h2> <div className="grid grid-cols-1 gap-4"> {financialData.map((item, index) => ( <div key={index} className="bg-white p-4 rounded-lg shadow"> <h3 className="text-gray-600">{item.metric}</h3> <p className="text-3xl font-sans font-bold tabular-nums">{item.value}</p> <span className={`text-sm ${item.growth.startsWith('+') ? 'text-green-500' : 'text-red-500'} proportional-nums`}> {item.growth} </span> </div> ))} </div> </div> ); }
Statistical Analysis Card
A component showing statistical data with different numeric styles for better readability.
export default function StatisticsCard() { const stats = [ { title: "Sample Size", value: "1,234", decimal: "0.567", percentage: "89.4%" }, { title: "Mean Value", value: "4,567", decimal: "0.890", percentage: "92.1%" }, { title: "Median", value: "2,345", decimal: "0.123", percentage: "78.5%" }, { title: "Standard Deviation", value: "3,456", decimal: "0.456", percentage: "95.7%" }, { title: "Variance", value: "5,678", decimal: "0.789", percentage: "88.3%" }, { title: "Confidence Level", value: "6,789", decimal: "0.234", percentage: "91.6%" } ]; return ( <div className="max-w-4xl mx-auto p-8"> <div className="grid grid-cols-2 gap-6"> {stats.map((stat, index) => ( <div key={index} className="bg-indigo-50 p-6 rounded-xl"> <h3 className="text-indigo-800 mb-4">{stat.title}</h3> <div className="space-y-2"> <p className="text-2xl font-sans font-semibold tabular-nums">{stat.value}</p> <p className="text-lg font-sans proportional-nums">{stat.decimal}</p> <p className="font-[Georgia] text-xl oldstyle-nums">{stat.percentage}</p> </div> </div> ))} </div> </div> ); }
Sports Scoreboard
A live scoreboard component with different numeric styles for scores and statistics.
export default function SportsScoreboard() { const matches = [ { team1: "Lakers", team2: "Warriors", score1: "108", score2: "115", quarter: "4th", time: "02:45" }, { team1: "Celtics", team2: "Bulls", score1: "98", score2: "92", quarter: "3rd", time: "06:30" }, { team1: "Nets", team2: "Heat", score1: "87", score2: "89", quarter: "2nd", time: "04:15" }, { team1: "Suns", team2: "Clippers", score1: "76", score2: "72", quarter: "1st", time: "08:20" }, { team1: "Bucks", team2: "76ers", score1: "95", score2: "99", quarter: "4th", time: "01:55" }, { team1: "Mavericks", team2: "Spurs", score1: "112", score2: "105", quarter: "Final", time: "00:00" } ]; return ( <div className="bg-gray-900 p-6 text-white"> <h2 className="text-2xl mb-6">Live Scores</h2> <div className="space-y-4"> {matches.map((match, index) => ( <div key={index} className="font-sans bg-gray-800 p-4 rounded-lg flex justify-between items-center"> <div className="flex flex-col flex-1 text-center"> <span className="text-2xl mx-4 tabular-nums">{match.score1}</span> <span className="text-xl">{match.team1}</span> </div> <div className="text-center px-8"> <span className="text-sm ordinal">{match.quarter}</span> <br /> <span className="text-lg proportional-nums">{match.time}</span> </div> <div className="flex flex-col flex-1 text-center"> <span className="text-2xl mx-4 tabular-nums">{match.score2}</span> <span className="text-xl">{match.team2}</span> </div> </div> ))} </div> </div> ); }
Stock Market Ticker
A stock market ticker component with different numeric styles for prices and changes.
export default function StockTicker() { const stocks = [ { symbol: "AAPL", price: "156.78", change: "+2.45", volume: "12.5M" }, { symbol: "GOOGL", price: "2,789.45", change: "-15.67", volume: "8.2M" }, { symbol: "MSFT", price: "345.23", change: "+5.89", volume: "10.1M" }, { symbol: "AMZN", price: "3,456.78", change: "-28.90", volume: "15.7M" }, { symbol: "TSLA", price: "789.12", change: "+12.34", volume: "20.3M" }, { symbol: "META", price: "234.56", change: "+1.23", volume: "9.8M" } ]; return ( <div className="bg-black p-6"> <div className="flex flex-wrap gap-4"> {stocks.map((stock, index) => ( <div key={index} className="font-sans bg-gray-900 p-4 rounded-lg text-white"> <h3 className="text-lg font-bold">{stock.symbol}</h3> <p className="text-2xl tabular-nums">${stock.price}</p> <p className={`text-sm ${stock.change.startsWith('+') ? 'text-green-400' : 'text-red-400'} proportional-nums`}> {stock.change} </p> <p className="text-gray-400">Vol: {stock.volume}</p> </div> ))} </div> </div> ); }
Scientific Calculator Display
A calculator display component with different numeric styles for different types of numbers.
export default function CalculatorDisplay() { const calculations = [ { expression: "√256", result: "16.0000", type: "root" }, { expression: "sin(45°)", result: "0.7071", type: "trigonometry" }, { expression: "log(100)", result: "2.0000", type: "logarithm" }, { expression: "e^2", result: "7.3891", type: "exponential" }, { expression: "3.14159", result: "π", type: "constant" }, { expression: "75!", result: "2.4809×10^109", type: "factorial" } ]; return ( <div className="bg-gray-100 p-6"> <div className="font-[Inter] max-w-md mx-auto bg-white rounded-xl shadow-lg p-6"> <div className="space-y-4"> {calculations.map((calc, index) => ( <div key={index} className="border-b border-gray-200 pb-3"> <div className="flex justify-between items-center"> <span className="text-gray-600 proportional-nums">{calc.expression}</span> <span className="text-xl slashed-zero tabular-nums">{calc.result}</span> </div> <span className="text-sm text-gray-500">{calc.type}</span> </div> ))} </div> </div> </div> ); }
Best Practices
Maintain Design Consistency
When using font variant numeric utilities, align the numeric style with the overall design system. For example, if tabular-nums
is chosen for a data-heavy dashboard, all numerical elements should follow the same rule to maintain a uniform grid. Avoid mixing lining-nums
and oldstyle-nums
randomly within the same context, as it can create a disjointed reading experience.
For structured content like invoices or time logs, standardizing numeric typography ensures that all numbers align correctly. Establish guidelines on when and where each style should be applied, ensuring that designers and developers maintain coherence across the UI.
Leverage Utility Combinations
Combining font variant numeric utilities with other utilities like- font size, font family, letter spacing, etc. help to enhance clarity and usability. Thoughtfully integrating spacing, color, and typography can enhance legibility and create a visually appealing interface.
When presenting numbers in an interactive setting, such as a calculator or stock tracker, consider using tabular-nums
alongside text-right
to align numerical content neatly. This pairing avoids jagged edges and improves scanability. Additionally, using slashed-zero
with monospaced fonts enhances differentiation between similar characters (e.g., 0
and O
), reducing ambiguity.
Accessibility Considerations
Enhance Readability and Navigability
The choice between tabular-nums
and proportional-nums
can significantly impact how numbers appear in structured layouts, particularly for users with cognitive impairments or reading difficulties.
Using tabular-nums
for data tables improves clarity by maintaining a consistent width, allowing readers to interpret numbers without unexpected spacing inconsistencies. This prevents issues where misaligned numbers become difficult to track. For general text, proportional-nums
ensures that numbers blend naturally within paragraphs, enhancing readability without creating unnecessary visual disruptions.
Focus on High Contrast
Ensuring sufficient contrast for numeric text is crucial for accessibility, particularly for users with low vision. When using font variant numeric utilities, it's important to pair them with high-contrast colors. Without adequate contrast, numbers can become difficult to distinguish.
Consider using dark text on a light background or light text on a dark background. Additionally, applying high font weight or letter spacing to further enhance legibility.
Beyond basic contrast considerations, it’s essential to meet the Web Content Accessibility Guidelines (WCAG) contrast ratio recommendations. For normal text, the minimum required contrast ratio is 4.5:1
, while larger text should maintain at least 3:1
contrast.