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

layup

v0.2.2

Published

CSS Grid Layout made easy.

Downloads

18

Readme

layup

A tiny React helper for CSS layout using named areas and lines from CSS Grid.

Adaptable to any React styling solution. Includes adapters for:

Install

$ yarn add layup
$ npm install --save layup

Looks like…

(Using inline styles – but see below for more examples.)

import Layout from 'layup/inline'

const foodLayout = {
  gridTemplateAreas: `
    'pizza .     .    '
    '.     tacos .    '
    '.     .     ramen'
  `
}

<Layout style={foodLayout} areas={{
  pizza: <Pizza />,
  tacos: <Tacos />,
  ramen: <Ramen />
}} />

FoodLayout

Motivation

  • Many React layout components have you define your sizing, alignment, and spacing via props. This makes responsive design harder. (It’s why Styled System has to support array values for every prop, for example.) Defining as much layout in CSS as possible lets you move things around via standard CSS features like @media queries – the layout isn’t “stuck” in JavaScript.
  • You shouldn’t have to add individual styling properties (like mb or marginBottom) to every component you write just because there’s different whitespace around them sometimes.
  • Using the margin property for layout is often arbitrary and doesn’t make sense for UI layout. Only in rare circumstances should UI elements own the whitespace separating them.

What’s wrong with margin?

Strong opinion time! Using the margin property never made sense in the web app/component world. It’s a relic from the very first version of CSS, when we were laying out paragraphs of text in 1997. CSS Grid antiquates this practice. People just haven’t caught on yet.

Examples? OK.

Suppose each of these “page actions” on GitHub were a component:

How do you think the spacing between them is defined? Maybe they’re each inside a container with padding. Maybe they each have a left margin of 10px. Maybe they each have a right margin of 10px, except for the :last-child which has 0. (In this case, the latter is exactly what GitHub has done.)

Which method is “correct”? Well, none in particular. When you’ve been writing CSS for a long time, you just develop an intuition for this. It could depend on what other page elements are nearby. But mostly, it’s arbitrary.

But why do the individual components need to “own” the whitespace between them? What if they’re used in other contexts that call for different spacing? Are we just supposed to override their margins every time? Wouldn’t it be nice if the component’s styles stopped at its actual borders, making it easier to use in other places?

CSS Grid offers a new solution to this problem. In this case, the container element can define the spacing between its children. It’s an inversion of the usual method of controlling whitespace, and one that (in my opinion) makes more sense. The children don’t need to concern themselves with spacing.

.PageActions {
  display: grid;
  grid-auto-flow: column;
  grid-gap: 10px;
}

What if the spacing between elements isn’t constant? Take this screen from dribbble for example:

How is that spacing defined?

Instead of each of those elements worrying about the overall layout, we could leave them margin-less and have the container lay them out with CSS Grid like so:

.SignUp {
  display: grid;
  grid-template-rows:
    [twitter] auto
    10px
    [facebook] auto
    10px
    [google] auto
    15px
    [orSeparator] auto
    15px
    [email] auto
    30px
    [signIn];
}

The container element is then free to arrange these rows differently (even showing them in a different order) at different breakpoints. All the child elements need to do is define their grid-row name. This library is a helper for doing exactly that!

Usage

The Layout component accepts areas, columns, and rows props. You should only pass one of these. The value can be an object directly mapping area/line names to child components:

<Layout
  rows={{
    header: <Title>Leave a comment</Title>,
    body: <TextInput />,
    footer: <SubmitButton />
  }}
/>

…or an array that will be used to pair area/line names with the children passed to Layout:

<Layout rows={['header', 'body', 'footer']}>
  <Title>Leave a comment</Title>
  <TextInput />
  <SubmitButton />
</Layout>

How you define the actual layout of the areas/columns/rows depends on your styling solution. Examples follow.

…with styled-components

Layout and its children receive their styling from className. Define the grid layout using styled():

import styled from 'styled-components'
import Layout from 'layup/styled'

const FoodLayout = styled(Layout)`
  grid-template-areas:
    'pizza .     .    '
    '.     tacos .    '
    '.     .     ramen';
`

<FoodLayout areas={{
  pizza: <Pizza />,
  tacos: <Tacos />,
  ramen: <Ramen />
}} />

…with Emotion

Layout and its children receive their styling from className. Either use styled() (see the styled-components example above) or define the grid layout using css:

import { css } from 'emotion'
import Layout from 'layup/emotion'

const foodLayout = css`
  grid-template-areas:
    'pizza .     .    '
    '.     tacos .    '
    '.     .     ramen';
`

<Layout className={foodLayout} areas={{
  pizza: <Pizza />,
  tacos: <Tacos />,
  ramen: <Ramen />
}} />

…with glamor

Layout and its children receive their styling from className. Define the grid layout using css:

import { css } from 'glamor'
import Layout from 'layup/glamor'

const foodLayout = css({
  gridTemplateAreas: `
    'pizza .     .    '
    '.     tacos .    '
    '.     .     ramen'
  `
})

<Layout className={foodLayout} areas={{
  pizza: <Pizza />,
  tacos: <Tacos />,
  ramen: <Ramen />
}} />

…with inline styles

Layout receives its styling from style. Children must also support the style prop:

import Layout from 'layup/inline'

const foodLayout = {
  gridTemplateAreas: `
    'pizza .     .    '
    '.     tacos .    '
    '.     .     ramen'
  `
}

<Layout style={foodLayout} areas={{
  pizza: <Pizza />,
  tacos: <Tacos />,
  ramen: <Ramen />
}} />

Adapting to any styling solution

All you need to do is define two components: Grid and Cell. Pass them to the createLayout function to get your Layout component.

Grid should:

  • Render an element with display: grid styling pre-applied.
  • Render its children, which will be an array of Cell elements.
  • Apply any further styling received from Layout. This is how users will customize the grid layout CSS.
    • You can do this via a prop like className or style, for example – it depends on your styling solution.

Cell should:

  • Return a clone of its child prop using React.cloneElement. child will be one of the components passed to Layout.
    • Note that because it returns a clone, from the perspective of CSS, the children passed to Layout are the grid cells (they aren’t wrapped by grid cells).
  • Apply grid-area, grid-column, or grid-row styling to the cloned child based on the received area, column, or row prop, respectively.
    • You can apply these styles via a prop like className or style, for example – it depends on your styling solution. The only requirement is that the child components must support that prop.

See the styled-components adapter for an example.