/picostyle

Ultra small CSS in JS library in 0.4 KB

Primary LanguageJavaScriptOtherNOASSERTION

Picostyle

482 gzip Build Status

Picostyle is a 0.4 KB CSS-in-JS library for use with frameworks that expose an h function.

Update: Picostyle is now faster by removing JSON.stringify and supports a new css function that returns a class name for Components that support a class attribute property.

Try it Online

  • 🚀 The smallest CSS-in-JS library: Only 0.4 KB (minified & gzipped).
  • 👏 Zero dependencies: And under 80 LOC.
  • 💅 Styled components: Gives you a styled component like styled-components that y'all love.

Currently tested with:

Installation

Install with npm or Yarn.

npm i picostyle

Then with a module bundler like Rollup or Webpack, use as you would anything else.

import picostyle from "picostyle"

Otherwise, download the latest release or load directly from unpkg or jsDelivr.

<script src="https://unpkg.com/picostyle"></script>

Then find it in window.picostyle.

Usage

Picostyle will work with any framework that exposes an h function. When you pass Picostyle an function h it returns a higher order function (HOF) that you can use exactly like the h you pass it.

Picostyle can now return an object with the style function and a new css fucntion when the new "return object" flag is true

import { h } from "some-framework"
import picostyle from "picostyle"

const style = picostyle(h)

Or

import { h } from "some-framework"
import picostyle from "picostyle"

const returnObject = true
const { style, css } = picostyle(h, returnObject)

The HOF accepts a tag name (or an unstyled component) and returns a function that accepts JSON styles.

// Styled component from tag name
const Wrapper = style("div")({
  minHeight: "100vh",
  background: "#000",
})

// Styling an un-styled component
const Component = (props, text) => h("h1", props, text)
const Text = style(Component)({
  color: "#fff",
})

// Styling a component that supports a class name attribute
const Component = (state) => (
  h("h1",
    { 
      class: css( { color: "#fff" } )
    }
)

If you want to change the style based on the props, you can do it by passing a function, instead of JSON styles.

// Here we set the color of the button, based on the color prop
const Button = style("button")(props => ({
  color: props.color
}))

You can also use @keyframes animation importing keyframes function.

import picostyle, { keyframes } from 'picostyle'

const zoom = keyframes({
  from: {
    transform: 'scale(0.5)'
  },
  to: {
    transform: 'scale(2)'
  },
})

const Container = ps('div')({
  animation: `${zoom} 300ms`,
})

You can now use the styled components to build your app.

const App = h("main", {}, [
  Wrapper({}, Text("Scoping CSS is hard")),
  Wrapper({}, Text("Not with styled components!")),
  Wrapper({color: 'red'}, Button("I'm red!")),
])

Picostyle transforms any provided JSON styles into plain CSS styles and injects them into a style tag in the head of the document; all under unique style identifiers (USI). Each styled component is given a USI as a class name.

Because the output is a stylesheet and not inline styles. You can use all valid CSS in your JSON styles. For example:

  • Media Queries (@media (orientation: portrait))
  • Pseudo-element and Pseudo-classes (::before, :hover, :last-child).
  • Nested child styles (> h1, > *+*)

Preact example

Get the Code

import picostyle from "picostyle"
import { h, render } from 'preact';

const ps = picostyle(h)

const keyColor = "#f07";

const Text = ps("a")({
  fontSize: "64px",
  cursor: "pointer",
  color: "#fff",
  padding: "0.4em",
  transition: "all .2s ease-in-out",
  textDecoration: "none",
  ":hover": {
    transform: "scale(1.3)",
  },
  "@media (max-width: 450px)": {
    fontSize: "32px",
  },
})

const Wrapper = ps("div")({
  display: "flex",
  justifyContent: "center",
  alignItems: "center",
  width: "100vw",
  height: "100vh",
  backgroundColor: keyColor,
})

render((
  <Wrapper>
    <Text href="https://github.com/morishitter/picostyle">Picostyle meets Preact</Text>
  </Wrapper>
), document.body);

Hyperapp Example

Get the Code

import { h, app } from "hyperapp"
import picostyle from "picostyle"

const style = picostyle(h)
const theme = "hotpink" // Try change the theme to white

const Wrapper = style("div")({
  display: "flex",
  width: "100%",
  height: "100vh",
  backgroundColor: theme,
  "> h1": { cursor: "pointer" }
})

const Text = style("h1")({
  fontSize: "calc(10px + 5vmin)",
  color: theme === "white" ? "black" : "white",
  margin: "auto",
  transition: "transform .2s ease-out",
  ":hover": {
    transform: "scale(1.2)",
  },
  "@media (orientation: landscape)": {
    fontWeight: "bold",
  },
})

app({
  state: {
    text: "Picostyle"
  },
  view: (state) =>
    <Wrapper>
      <Text>Hello { state.text }</Text>
    </Wrapper>
})

Ultradom Example

Get the Code

/** @jsx */

import {h, patch} from "ultradom"
import picostyle from "picostyle"

const ps = picostyle(h)

function view(state) {
  const keyColor = "#f07";

  const Text = ps("h1")({
    fontSize: "64px",
    cursor: "pointer",
    color: "#fff",
    padding: "0.4em",
    transition: "all .2s ease-in-out",
    ":hover": {
      transform: "scale(1.3)",
    },
    "@media (max-width: 450px)": {
      fontSize: "32px",
    },
  })

  const Wrapper = ps("div")({
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    width: "100vw",
    height: "100vh",
    backgroundColor: keyColor,
  })

  return (
    <Wrapper>
      <Text>{state.trim() === "" ? ":)" : state}</Text>
    </Wrapper>
  )
}

document.body.appendChild(patch(view("Hello, Picostyle")))