npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lettrine

v0.1.0

Published

Drop-cap ornaments from real books, applied to any element

Readme

Lettrine

Ornamental drop caps from real books. 26 letters, five variants each, as inline SVG.
Works with any framework, accessible and customizable.

Comes in two builds:

  • Default dynamic version for builds with dynamic content
  • Tree-shakable version for static builds Same attribute, same styling, same behaviour. See Choosing a build.

Install

npm install lettrine

Usage

Import it once, anywhere in your app, then tag any element:

import 'lettrine';
<p data-lettrine>Lorem ipsum dolor sit amet, consectetur adipiscing elit</p>

Without a bundler:

<script type="module" src="node_modules/lettrine/src/index.js"></script>

Choosing a variant

Every letter comes in five variants. A random variant is used by default, choose one by passing a number from 1 to 5:

<p data-lettrine>Chosen for you, and stable across reloads.</p>
<p data-lettrine="3">Always variant three.</p>

You can also name the glyph directly (needed for the tree-shakeable build):

<p data-lettrine="A1">Arms and the man I sing…</p>

Variant 0 is a special case, it uses the first letter of the text as the drop cap:

<p data-lettrine="0">Plain V, no ornament.</p>

Styling

Everything is a CSS custom property, so it cascades like any other style:

| Property | Default | | | --- | --- | --- | | --lettrine-lines | 3 | how many lines tall the ornament is | | --lettrine-line-height | 1.5 | set this to your body line-height | | --lettrine-color | unset | ornament colour; inherits the text colour by default | | --lettrine-background | transparent | fills the ornament's box, behind the glyph | | --lettrine-gap-right | .5em | space between ornament and text | | --lettrine-gap-bottom | .1em | space below the ornament |

Example usage:

:root         { --lettrine-lines: 3; --lettrine-line-height: 1.6 }
.chapter-open { --lettrine-lines: 5; --lettrine-color: #7a3b12 }
.reversed     { --lettrine-background: #7a3b12; --lettrine-color: #f9f6ef }

Choosing a build

| | lettrine | lettrine/static | | --- | --- | --- | | setup | import it, done | declare the glyphs you use and pass them in | | works with | any text, including dynamically changing text | letters known when you build | | in the build | every glyph, as separate chunks | only the glyphs you need |

Use the default unless you have a reason not to. It has no setup, it copes with whatever text turns up, and it is the only one that works when content comes from a CMS, a search result, user input, or anything else you can't enumerate in advance.

Use the static build when you know your letters at build time: a book, fixed chapters, a marketing site, and you want the smallest possible output.

The static build

Name the glyphs you use. A bundler keeps only those; the other glyphs are never emitted:

import { lettrine, observe } from 'lettrine/static';
import { A1, M2 } from 'lettrine/glyphs';

const glyphs = { A1, M2 };
await lettrine({ glyphs });
<p data-lettrine="A1">Arms and the man I sing…</p>

[!IMPORTANT] In the static build, you need to name the specific glyph in the attribute, not just the variant.

API

Only needed if you want manual control.

import { lettrine, decorate, reset, observe } from 'lettrine';

await lettrine();                // decorate everything now; resolves to how many it changed
await lettrine({ root, attr });  // limit to a subtree, or use a different attribute
await decorate(el, { variant: 2 });  // a single element
reset(el);                       // put the original text back
const stop = observe({ root });  // watch a subtree for any data-lettrine attribute; call stop() when done

Good to know

  • Accents are handled: École gets the E ornament.
  • Opening quotes and brackets are swallowed by the ornament, the way print does it — « Élan », ¿Qué tal?.
  • Elements that don't start with a letter are left alone.
  • The original text stays in the page, so screen readers and copy-paste are unaffected.

Development

make play     # serve playground examples
make build    # rebuild the glyph data from letters/*.svg