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

@artusdev/tailwind-underlines

v1.0.0

Published

A Tailwind CSS v4 plugin that adds advanced and animated underline utilities for flexible text decoration control.

Readme

@artusdev/tailwind-underlines

Advanced animated underline utilities for Tailwind CSS v4.

✨ Features

  • 🎨 Fully Customizable - Control thickness, duration, timing, offset, and color
  • 🔄 Bidirectional Control - Independent in/out animation directions
  • 🎯 Pure CSS - Zero JavaScript dependencies
  • 🌳 Tree-Shakeable - Only includes classes you use
  • Tailwind v4 Ready - Native support for arbitrary values and theme tokens
  • Accessible - Works with all Tailwind variants (focus, group-hover, etc.)

📦 Installation

npm install @artusdev/tailwind-underlines

🚀 Quick Start

1. Import the plugin in your CSS:

@import "@artusdev/tailwind-underlines";

2. Add to your HTML:

<a class="underline-base hover:underline-expanded"> Hover me </a>

That's it! You now have a beautiful animated underline.

📖 How It Works

The plugin uses a two-class pattern:

| Class | Purpose | | ------------------------------ | --------------------------------------------------------------------------- | | underline-base | Sets up the underline container, variables, and collapsed state | | [variant]:underline-expanded | Triggers the underline animation (e.g., hover:, focus:, group-hover:) |

🎨 Customization

Direction

Simple (Bidirectional)

Same direction for both enter and exit animations:

| Class | Effect | | ------------------ | ---------------------- | | underline-left | Left → Right (default) | | underline-right | Right → Left | | underline-center | Center → Outward |

<a class="underline-base underline-center hover:underline-expanded"> Center expand </a>

Advanced (Independent Control)

Control entry and exit directions separately - 9 possible combinations:

| Enter From | Exit To | Classes | | ---------- | ------- | ----------------------------------------- | | Left | Right | underline-in-left underline-out-right | | Center | Left | underline-in-center underline-out-left | | Right | Center | underline-in-right underline-out-center |

<a class="underline-base underline-in-left underline-out-right hover:underline-expanded">
    Enter left, exit right
</a>

Thickness

| Type | Example | Output | | ---------------- | ------------------------------ | ------------- | | Theme tokens | underline-thickness-thin | 1px | | | underline-thickness-normal | 2px (default) | | | underline-thickness-thick | 4px | | Bare integers | underline-thickness-5 | 5px | | Arbitrary values | underline-thickness-[0.5rem] | 0.5rem |

Duration

| Type | Example | Output | | ---------------- | --------------------------- | --------------- | | Theme tokens | underline-duration-fast | 150ms | | | underline-duration-normal | 250ms (default) | | | underline-duration-slow | 500ms | | Bare integers | underline-duration-1000 | 1000ms | | Arbitrary values | underline-duration-[1.5s] | 1.5s |

Timing Functions

| Type | Example | Effect | | ------------- | ---------------------------------------------- | --------------------- | | Theme presets | underline-timing-linear | Linear | | | underline-timing-ease | Ease | | | underline-timing-ease-in | Ease-in | | | underline-timing-ease-out | Ease-out | | | underline-timing-ease-in-out | Ease-in-out (default) | | | underline-timing-bounce | Elastic bounce | | | underline-timing-spring | Spring overshoot | | Arbitrary | underline-timing-[cubic-bezier(0.4,0,0.2,1)] | Custom curve |

Offset

Control vertical positioning. Note: Positive = down, negative = up.

| Pattern | Example | Result | | ------------------ | ---------------------------- | ------------- | | Bare integers | underline-offset-3 | 3px (down) | | Arbitrary | underline-offset-[0.5rem] | 0.5rem (down) | | Negative prefix | -underline-offset-3 | -3px (up) | | Negative arbitrary | -underline-offset-[0.5rem] | -0.5rem (up) |

Color

Supports all tailwindcss colors, your custom colors and arbitrary color values (defaults to currentColor):

<a class="underline-base underline-color-[#3b82f6] hover:underline-expanded"> Custom color </a>

💡 Examples

Basic

<a class="underline-base hover:underline-expanded"> Hover me </a>

Centered Fast Animation

<a class="underline-base underline-center underline-duration-fast hover:underline-expanded">
    Quick center expand
</a>

Button with Bounce Effect

<button
    class="underline-base underline-thickness-thick underline-timing-bounce active:underline-expanded"
>
    Click me
</button>

Complex Styling

<a
    class="underline-base underline-thickness-[8px] underline-duration-[2s]
          underline-color-[#3b82f6] underline-in-left underline-out-right
          hover:underline-expanded"
>
    Fully customized
</a>

Navigation Menu

<nav>
    <a class="group" href="/about">
        <span class="underline-base underline-center group-hover:underline-expanded"> About </span>
    </a>
</nav>

Accessible Focus State

<a class="underline-base focus:underline-expanded focus-visible:outline-2"> Tab to focus </a>

🎨 Extending the Theme

Add custom tokens in your CSS:

@theme {
    --underline-thickness-hairline: 0.5px;
    --underline-duration-ultra-fast: 75ms;
    --underline-timing-elastic: cubic-bezier(0.68, -0.55, 0.27, 1.55);
}

Use them like built-in tokens:

<a
    class="underline-base underline-thickness-hairline underline-duration-ultra-fast underline-timing-elastic hover:underline-expanded"
>
    Custom theme
</a>

🔧 API Reference

Utilities

| Utility | Description | Default | | ----------------------- | ---------------------- | -------------- | | underline-base | Base setup (required) | - | | underline-expanded | Shows the underline | - | | underline-left | Left to right | ✓ | | underline-right | Right to left | - | | underline-center | Center outward | - | | underline-in-* | Entry direction | left | | underline-out-* | Exit direction | left | | underline-thickness-* | Thickness | 2px (normal) | | underline-duration-* | Animation duration | 250ms (normal) | | underline-timing-* | Timing function | ease-in-out | | underline-offset-* | Vertical offset (down) | 0px | | -underline-offset-* | Vertical offset (up) | - | | underline-color-* | Color | currentColor |

CSS Variables

You can also control underlines via CSS custom properties:

.my-link {
    --underline-thickness: 3px;
    --underline-duration: 500ms;
    --underline-timing: cubic-bezier(0.4, 0, 0.2, 1);
    --underline-offset: 2px; /* positive = down, negative = up */
    --underline-color: #3b82f6;
    --underline-origin-in: left;
    --underline-origin-out: right;
}

⚙️ How It Works

The plugin uses CSS transforms for GPU-accelerated animations:

  1. underline-base creates a pseudo-element (::after) scaled to 0 width
  2. underline-expanded scales it to full width (scaleX(1))
  3. Transform origin controls the animation direction
  4. CSS custom properties enable runtime customization

Result: Buttery-smooth 60fps animations with zero JavaScript.

🌐 Browser Support

  • ✅ All modern browsers (Chrome, Firefox, Safari, Edge)
  • ✅ CSS Custom Properties required
  • ✅ CSS Transforms required

📄 License

This project is licensed under the MIT License.