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 🙏

© 2024 – Pkg Stats / Ryan Hefner

hypostyle

v3.3.2

Published

Minimalist 5th Generation CSS-in-JS built for concision and extension. Fast af, powered by nano-css.

Downloads

62

Readme

hypostyle

npm version test coverage npm bundle size

Minimalist 5th Generation CSS-in-JS built for concision and extension. Fast af, powered by nano-css.

npm i hypostyle

Why

Typical 4th gen CSS-in-JS can be very verbose. hypostyle provides a way of authoring CSS in Javascript using shortcuts and abbreviations — like atomic CSS and frameworks like Tailwind — at a fraction of the bundle size. hypostyle is also framework-agnostic, meaning it can be adapted into any UI framework and any CSS-in-JS library that supports style objects.

import { hypostyle } from 'hypostyle'

const { css } = hypostyle({
  breakpoints: ['400px', '800px', '1200px'],
  tokens: {
    color: {
      primary: '#ff4567',
    },
    space: [0, 4, 8, 12, 16, 20, 24, 28, 32],
  },
  shorthands: {
    c: ['color'],
    px: ['paddingLeft', 'paddingRight'],
  },
})

const classname = css({
  c: 'primary',
  px: [4, 8],
})

function Component() {
  return <div className={classname} />
}

👇

color: #ff4567;
padding-left: 16px;
padding-right: 16px;
@media (min-width: 400px) {
  padding-left: 32px;
  padding-right: 32px;
}

Contents

Getting Started

The hypostyle() function is used to configure a theme and return an instance. Your theme can contain the following properties:

  • tokens - design system tokens, like colors, spacing, etc
  • breakpoints - array of breakpoint widths (optional)
  • shorthands - abbreviated properties that map to one or more CSS properties and (optionally) design tokens
  • macros - boolean properties mapped to pre-defined style objects
  • variants - named groups of pre-defined style objects
  • properties - config supported CSS properties

Presets

Hypostyle includes optional preset objects with a starter set of tokens, shorthands, and macros. Source code.

import * as presets from 'hypostyle/presets'

const { css } = hypostyle(presets)

Responsive Values

All values can be responsive by passing an array of values. This array maps to the breakpoints array on your theme. The first value is mobile, and the remaining values are convered into @media breakpoints.

css({
  d: ['block', 'none'],
})

Will generate:

.__3sxrbm {
  display: block;
}
@media (min-width: 400px) {
  .__3sxrbm {
    display: none;
  }
}

Alternatively — and useful if you want to only specify a single breakpoint — you can use object syntax. Just use the indices as object keys:

css({
  d: { 1: 'none' },
})
@media (min-width: 400px) {
  .__3sxrbm {
    display: none;
  }
}

Tokens & Shorthands

Tokens are either objects of named values, or arrays (scales) of values.

const { css } = hypostyle({
  tokens: {
    color: {
      primary: '#ff4557',
    },
    space: [0, 4, 8, 12, 16],
  },
})

Tokens are associated with configurable CSS properties so that you can use token values in your styles. By default, most CSS properties are supported and are self referencing.

Shorthands are like shortcuts that allow you to abbreviate CSS these properties. The rest of the above example could look like this:

const { css } = hypostyle({
  tokens: {
    color: {
      primary: '#ff4557',
    },
    space: [0, 4, 8, 12, 16],
  },
  shorthands: {
    bg: 'background',
  },
})

Which can be used like this, because background is associated with the color tokens by default:

css({ bg: 'primary' }) // => { background: '#ff4567' }

Macros

macros are simple boolean values that expand to be full style objects. The style objects can use any shorthands or tokens you have configured.

const { css } = hypostyle({
  macros: {
    cover: { top: 0, bottom: 0, left: 0, right: 0 },
  },
})

css({ cover: true }) // => { top: 0, bottom: 0, ... }

These are most helpful when used with JSX (via React, hyposcript, or otherwise) i.e.:

<Box cover />

Variants

Slightly higher-level than macros are variants, which allow you to define named style blocks based on property values. Again, your style blocks here can use any shorthands and tokens you've configured.

import * as presets from 'hypostyle/presets'

const { css } = hypostyle({
  ...presets,
  variants: {
    appearance: {
      link: {
        c: 'blue',
        textDecoration: 'underline',
      },
    },
  },
})

Which look like this when used:

css({ appearance: 'link' }) // => { color: 'blue', textDecoration: 'underline' }

Writing CSS

Pseudos & Nested Selectors

const link = css({
  color: 'black',
  '&:hover': {
    color: 'blue',
  },
  '.icon': {
    transform: 'translateX(5px)',
  },
})

Global Styles

Also included alongside css is injectGlobal.

import { hypostyle } from 'hypostyle'
import * as presets from 'hypostyle/presets'

const { injectGlobal } = hypostyle(presets)

injectGlobal({
  'html, body': {
    c: '#333',
    boxSizing: 'border-box',
  },
})

Keyframes

Also also included alongside css is keyframes.

const { keyframes } = hypostyle(presets)

const animation = keyframes({
  '0%': {
    opacity: 0,
  },
  '100%': {
    opacity: 1,
  },
})

css({
  animation: `${animation} 1s linear infinite`,
})

Configuring CSS Properties

Hypostyle comes with built-in support for most CSS properties. To add additional support, have a look at the properties.js file for API, and pass your additional props to the constructor. Example:

const hypo = hypostyle({
  ...,
  tokens: {
    ...,
    radii: ['4px', '8px']
  },
  shorthands: {
    ...,
    bTLR: 'borderTopLeftRadius'
  },
  properties: {
    borderTopLeftRadius: {
      token: 'radii'
    }
  }
})

Usage:

hypo.style({ bTLR: 1 }) // => { borderTopLeftRadius: '8px' }

Server Usage

hypostyle is isomorphic!

const { css, flush, injectGlobal } = hypostyle(presets)

injectGlobal({ '*': { boxSizing: 'border-box' } })

const classname = css({ c: 'primary' })
const stylesheet = flush()

const html = `
<!DOCTYPE html>
<html>
  <head>
    <style>${stylesheet}</style>
  </head>
  <body>
    <div class="${classname}">Hello world</div>
  </body>
</html>
`

Related

License

MIT License © Sure Thing