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 🙏

© 2025 – Pkg Stats / Ryan Hefner

afro

v3.0.1

Published

refined aphrodite

Readme

Fly CSS-in-JS modules

afro

Features

  • You can actually write CSS in your Javascript
  • Composeable stylesheets with lazy compilation
  • Hack-free psuedo-classes, @keyframes, @media, & @font-face support
  • Not tied to any build system or React
  • Supports parent > child relationships
  • Autoprefixed for all browser vendors
  • Simple Server-side CSS support
  • Content-addressed class names
  • Auto-injected <style> tag
  • 8kb total
  • Deduped CSS

Installation

npm install afro

Example

let domify = require('domify')
let Afro = require('..')

let container = Afro(`
  @font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: 400;
    src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format('woff2');
  }

  .red {
    font-family: 'Open Sans';
    background: red;
  }
`)

let span = Afro(`
  .blue {
    font-family: 'Open Sans';
    background: blue;
  }

  @media (min-width: 33em) {
    .blue {
      background: turquoise;
    }
  }
`)

let css = Afro(container, span)

document.body.appendChild(domify(`
  <div class="${css.red}">
    <span class="${css.blue}">hi there!</span>
    <span class="${css.blue}">hi there!</span>
  </div>
`)

// Or if you want to generate a static string and not inject
document.body.appendChild(domify(`
  <style type="text/css" afro static>${css}</style>
  <div class="${css.red}">
    <span class="${css.blue}">hi there!</span>
    <span class="${css.blue}">hi there!</span>
  </div>
`)

How is this different than X

Aphrodite

Afro is a spiritual successor to Aphrodite. Aphrodite uses JSON as the way to write CSS, where Afro you just write plain CSS.

Aphrodite also uses global singletons on the server-side to generate CSS which prevents you from doing any sort of concurrency.

Aphrodite doesn't yet support parent > child relationships like this one parent:hover child { ... }. With Afro that relationship just works.

Lastly, Aphrodite writes CSS dynamically as you need it in your components. Afro inserts all the CSS (deduped) at once, making the model quite a bit simpler. There may be some benefits to dynamically inserted CSS, like less work to do on initialization, but there are definitely a few caveats.

CSS Modules

CSS modules introduce new syntax into CSS via composes and require a build system like postcss or webpack to make it work.

Where you can help

Autoprefixer for CSS properties

Right now the autoprefixing library uses inline style names which are camel-cased. We could skip this step entirely if we had an autoprefixer library that could deal with hyphened properties.

FAQ

Isn't the <style> injection feature creep?

Good observation! This is something I was planning to exclude from this library. The reason it's important to inject a style tag is that allows your modules to work standalone.

You can require a module and run that code and it will just work without any style-specific initialization on your end. With that being said, it's good practice to export your styles alongside your component so you can compose the styles together.

If you're building an app and you have control over the styles, you'll want to compose all the styles together to get the benefits of de-duped CSS.

You also may want to ignore the injection all together and just render the CSS to a string and stick it in a React <style> element

Tests

npm install
make test

Credits

Logo is from Oliviu Stoian.

License

MIT