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

responsive-style

v1.3.0

Published

Functions that take a value or multiple values grouped by breakpoints, and returns an object with CSS declarations and media queries that can be passed to a CSS-in-JS library of choice.

Downloads

2,452

Readme

Responsive Style

Functions that take a value or multiple values grouped by breakpoints, and returns an object with CSS declarations and media queries that can be passed to a CSS-in-JS library of choice.

This is utility functions that are designed to be used to create your reuseable components and are to be set up a few times.

Install

npm install responsive-style

For the coming examples we'll be using React the css function from the @emotion/css package. Examples of how to use it with other libraries will come later.

createResponsiveStyle('blue', => color => ({ color }))
// returns ({ color: 'blue' })

createResponsiveStyle(['blue', { 700: 'red' }], color => ({ color }))
/* returns ({
  color: 'blue',
  '@media (min-width: 700px)': {
    color: 'red'
  }
})*/

You can also map the values to something else

createResponsiveStyle(color, value => themeColors[value])
createResponsiveStyle(size, textSize => ({ textSize }))
createResponsiveStyle(variant, value => ({
  '--text-color': variant !== 'dark' ? 'black' : 'white',
  backgroundColor: 'var(--text-color)',
}))

If you want to combine multiple values, you can use the responsiveStyles function.

createResponsiveStyles(
  { color: v => themeColors[v], backgroundColor: v => themeColors[v] },
  { color: 'red', backgroundColor: ['blue', { large: 'orange' }] },
  { breakpoints: { large: 1200 } }
)

Extractors

Sometimes you want to allow a style like margin or padding to be expressed like:

{ margin: 4 }
{ margin: '30px auto' }
{ margin: { top: 4, x: 'auto' } }
{ margin: [{ y: 8 }, { 400: { top: 20 }}] }

Create a reuseable mapping function that you use in your base components, or use the one provided with in this package.

import { marginMapper, paddingMapper, borderMapper, createResponsiveStyle } from 'responsive-style'
createResponsiveStyle(margin, marginMapper)
createResponsiveStyle(padding, paddingMapper)
createResponsiveStyle(border, borderMapper)

Media queries

Media queries can either be written manually:

;[
  { color: 'black' },
  {
    '@media (min-width: 700px) and (prefers-color-scheme: dark)': {
      color: 'white',
    },
  },
]

or by just passing a number as a breakpoint:

[{ color: 'red', { 500: { color: 'blue' }}}]

By default those breakpoints assume you implement mobile first, thus the breakpoints are set in (min-width: [breakpoint]px). This can be changed in (options)[#options].

Predefined media queries

If you pass predefined media queries in (options)[#options] you can set them by breakpoint names instead:

const breakpoints = {
  large: 1200,
  medium: 600,
  small: 460,
}
type Breakpoint = typeof breakpoints

function Text({ color }: { color: ResponsiveStyle<keyof typeof themeColors, Breakpoints> }) {
  return (
    <div
      className={css(createResponsiveStyle(color, value => themeColors[value], { breakpoints }))}
    />
  )
}

;<Text color={['purple-20', { large: 'orange-20' }]} />

Media query collisions

If you merge responsive styles to an object like this example:

className={css({
  ...createResponsiveStyle(color, value => themeColors[value]),
  ...createResponsiveStyle(display),
})}

If both responsive styles include the same media query, only the last one will be included. Either:

  1. Pass a key as the third argument: createResponsiveStyle(color, value => themeColors[value], 'color')
  2. Use createResponsiveStyles to merge the styles together
  3. Create unique classnames or use a function provided by your styling library that resolves those conflicts:
  cs(css(createResponsiveStyle(display), createResponsiveStyle(textSize)))

Examples

This is a basic example of how you can create a reuseable component that can take a color as a prop, or multiple grouped by breakpoints. The rest of the examples will be shown in tsx.

import React from 'react'
import css from 'emotion'
import { createResponsiveStyle } from 'responsive-style'

export default function Text({ color, ...rest }) {
  return <div className={css(createResponsiveStyle(color => ({ color })))} {...rest} />
}
import Text from './Text'

export const Example = () => (
  <Text color={['magenta', { 700: 'criomson', 1200: 'black' }]}>Hello World!</Text>
)
<style>
  .gwe3w {
    color: magenta;
  }
  @media (min-width: 700px) {
    .gwe3w {
      color: criomson;
    }
  }
  @media (min-width: 1200px) {
    .gwe3w {
      color: black;
    }
  }
</style>

<div class="gwe3w">Hello World!</div>