The CSS ::nth-letter Selector: A Dream We Can Almost Touch

From Putty P Hub, the free encyclopedia of technology

For decades, web designers have wished for a CSS pseudo-element that could target individual letters without JavaScript. The ::nth-letter selector, while nonexistent, fuels creative demos and discussions about CSS's limitations. This article explores the desire for this selector, the workarounds developers use, and the technical hurdles preventing its implementation.

What Exactly Is the ::nth-letter Selector and Why Do Developers Want It?

The ::nth-letter pseudo-element would let CSS target individual letters within a text — similar to ::first-letter but for any letter position. Developers have pleaded for it since at least 2003 because it would enable advanced typographical effects (like alternating skew or color per letter) without cluttering HTML with extra <span> tags. It would also reduce reliance on JavaScript for letter-level animations. The selector follows the same syntax as ::nth-child (e.g., ::nth-letter(even)), making it intuitive for anyone familiar with CSS selectors.

The CSS ::nth-letter Selector: A Dream We Can Almost Touch
Source: css-tricks.com

How Do Developers Currently Work Around the Missing Selector?

Without ::nth-letter, developers manually split text into individual letters using JavaScript or server-side logic, wrap each letter in a <span>, and then style those spans with CSS. This approach works but bloats markup, harms accessibility (if not careful), and makes dynamic updates painful. Some CSS trickery using background gradients or text-shadow can simulate basic letter effects, but true per-letter styling (e.g., applying a skew transform to every other letter) remains impossible without JavaScript. The demos in this article show how clean the code would look if the selector existed.

Can a CSS Polyfill Reliably Implement ::nth-letter?

Philip Walton (Google) famously attempted to build production-ready CSS polyfills but concluded it's impossible to do so reliably. The main issue: CSS polyfills must parse and modify CSS rules at runtime, which conflicts with browser security models and performance. While experimental frameworks exist (like Polyphil's abandoned tool), they break on any complex stylesheet or dynamic changes. Moreover, ::nth-letter would require the polyfill to analyze rendered text layout — something CSS alone cannot query. So while clever demos can simulate the effect in isolated environments, a universal polyfill remains a pipe dream.

What Are Some Practical Demos of ::nth-letter in Action?

Several working examples (using @supports hacks, JavaScript, or upcoming CSS features) show what ::nth-letter could accomplish. For instance, a text vortex scrolling effect that currently requires JavaScript could become pure CSS, as shown in one demo. Another demo mimics Temani Afif's direction-aware elastic hover by styling each letter individually — something that today demands <span> wrappers. Even a simple drop-cap extension (selecting the third letter) becomes trivial. These demos highlight the lost elegance of CSS when such a fundamental selector is missing.

Why Has ::nth-letter Not Been Added to CSS After All These Years?

The CSS Working Group has considered ::nth-letter but faces several obstacles. First, performance: recomputing styles when text content changes (e.g., via JavaScript) would be expensive for long blocks of text. Second, layout complexity: letters in inline contexts have variable widths and positions, making transforms or backgrounds tricky. Third, internationalization: many scripts (like Arabic or Thai) don't use simple letter units. Lastly, the elegance of CSS usually prefers whole-element selectors; letter-level selectors blur the line between styling and typesetting, which is often left to layout engines. Despite these challenges, the idea resurfaces periodically as CSS gains more capabilities.

Is There Any Hope for ::nth-letter in the Future?

Yes. The CSS Parser API (still in draft) could eventually allow authors to define custom pseudo-elements, including letter-level targeting. Additionally, the ::nth-letter idea aligns with the growing interest in text-decorations, text-justify, and text-wrap properties that behave typographically. As CSS continues to evolve — with container queries, sibling functions (sibling-index()), and better text layout — a standard way to style individual letters may finally become feasible. Meanwhile, developers can experiment with the JavaScript workarounds shown in this article, but the dream of a clean CSS-only solution remains strong.