{"id":13394013,"url":"https://github.com/exogen/layup","last_synced_at":"2025-03-20T03:30:50.381Z","repository":{"id":66194750,"uuid":"122248943","full_name":"exogen/layup","owner":"exogen","description":":basketball: CSS Grid Layout made easy.","archived":false,"fork":false,"pushed_at":"2018-05-10T19:19:22.000Z","size":981,"stargazers_count":24,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-16T14:53:56.664Z","etag":null,"topics":["css-grid","layout","react"],"latest_commit_sha":null,"homepage":"https://exogen.github.io/layup/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/exogen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-02-20T19:59:55.000Z","updated_at":"2020-10-22T17:54:43.000Z","dependencies_parsed_at":"2024-01-13T17:11:19.679Z","dependency_job_id":"c2996dda-0b9e-415b-8ce3-d0d249c3442d","html_url":"https://github.com/exogen/layup","commit_stats":{"total_commits":27,"total_committers":3,"mean_commits":9.0,"dds":0.07407407407407407,"last_synced_commit":"797fef83cb256d9e072bcc21699518471da24531"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Flayup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Flayup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Flayup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exogen%2Flayup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exogen","download_url":"https://codeload.github.com/exogen/layup/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244543734,"owners_count":20469552,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["css-grid","layout","react"],"created_at":"2024-07-30T17:01:05.701Z","updated_at":"2025-03-20T03:30:49.664Z","avatar_url":"https://github.com/exogen.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# layup\n\nA tiny React helper for CSS layout using\n[named areas and lines](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Layout_using_Named_Grid_Lines)\nfrom CSS Grid.\n\n**Adaptable to any React styling solution.** Includes adapters for:\n\n* [styled-components][]\n* [Emotion][]\n* [glamor][]\n* inline styles – no additional library necessary!\n\n## Install\n\n```console\n$ yarn add layup\n```\n\n```console\n$ npm install --save layup\n```\n\n## Looks like…\n\n(Using inline styles – but see below for more examples.)\n\n\u003ctable\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\n```jsx\nimport Layout from 'layup/inline'\n\nconst foodLayout = {\n  gridTemplateAreas: `\n    'pizza .     .    '\n    '.     tacos .    '\n    '.     .     ramen'\n  `\n}\n\n\u003cLayout style={foodLayout} areas={{\n  pizza: \u003cPizza /\u003e,\n  tacos: \u003cTacos /\u003e,\n  ramen: \u003cRamen /\u003e\n}} /\u003e\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n![FoodLayout](static/FoodLayout.png)\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n## Motivation\n\n* Many React layout components have you define your sizing, alignment, and\n  spacing via props. This makes responsive design harder. (It’s why\n  [Styled System](https://github.com/jxnblk/styled-system) has to support array\n  values for every prop, for example.) Defining as much layout in CSS as\n  possible lets you move things around via standard CSS features like `@media`\n  queries – the layout isn’t “stuck” in JavaScript.\n* You shouldn’t have to add individual styling properties (like `mb` or\n  `marginBottom`) to every component you write just because there’s different\n  whitespace around them sometimes.\n* Using the `margin` property for layout is often arbitrary and doesn’t make\n  sense for UI layout. Only in rare circumstances should UI elements own the\n  whitespace separating them.\n\n### What’s wrong with margin?\n\n**Strong opinion time!** Using the `margin` property never made sense in the web\napp/component world. It’s a relic from the very first version of CSS, when we\nwere laying out paragraphs of text in 1997. CSS Grid antiquates this practice.\nPeople just haven’t caught on yet.\n\nExamples? OK.\n\nSuppose each of these “page actions” on GitHub were a component:\n\n\u003cimg src=\"static/PageActions.png\" width=\"475\" alt=\"GitHub page actions\"\u003e\n\nHow do you think the spacing between them is defined? Maybe they’re each inside\na container with padding. Maybe they each have a left margin of 10px. Maybe they\neach have a right margin of 10px, except for the `:last-child` which has 0. (In\nthis case, the latter is exactly what GitHub has done.)\n\n\u003cimg src=\"static/PageActions-margin.png\" width=\"392\" alt=\"GitHub page actions with margin\"\u003e\n\nWhich method is “correct”? Well, none in particular. When you’ve been writing\nCSS for a long time, you just develop an intuition for this. It could depend on\nwhat other page elements are nearby. But mostly, it’s arbitrary.\n\nBut why do the individual components need to “own” the whitespace between them?\nWhat if they’re used in other contexts that call for different spacing? Are we\njust supposed to override their margins every time? Wouldn’t it be nice if the\ncomponent’s styles stopped at its actual borders, making it easier to use in\nother places?\n\nCSS Grid offers a new solution to this problem. In this case, the container\nelement can define the spacing between its children. It’s an inversion of the\nusual method of controlling whitespace, and one that (in my opinion) makes more\nsense. The children don’t need to concern themselves with spacing.\n\n```css\n.PageActions {\n  display: grid;\n  grid-auto-flow: column;\n  grid-gap: 10px;\n}\n```\n\n\u003cimg src=\"static/PageActions-grid.png\" width=\"403\" alt=\"GitHub page actions with grid\"\u003e\n\nWhat if the spacing between elements isn’t constant? Take this screen from\n[dribbble](https://dribbble.com/) for example:\n\n\u003cimg src=\"static/SignUp.png\" width=\"360\" alt=\"dribbble sign up\"\u003e\n\nHow is that spacing defined?\n\n\u003cimg src=\"static/SignUp-margins.gif\" width=\"378\" alt=\"dribbble sign up with margins\"\u003e\n\nInstead of each of those elements worrying about the overall layout, we could\nleave them margin-less and have the container lay them out with CSS Grid like\nso:\n\n```css\n.SignUp {\n  display: grid;\n  grid-template-rows:\n    [twitter] auto\n    10px\n    [facebook] auto\n    10px\n    [google] auto\n    15px\n    [orSeparator] auto\n    15px\n    [email] auto\n    30px\n    [signIn];\n}\n```\n\nThe container element is then free to arrange these rows differently (even\nshowing them in a different order) at different breakpoints. All the child\nelements need to do is define their `grid-row` name. This library is a helper\nfor doing exactly that!\n\n## Usage\n\nThe `Layout` component accepts `areas`, `columns`, and `rows` props. You should\nonly pass one of these. The value can be an object directly mapping area/line\nnames to child components:\n\n```jsx\n\u003cLayout\n  rows={{\n    header: \u003cTitle\u003eLeave a comment\u003c/Title\u003e,\n    body: \u003cTextInput /\u003e,\n    footer: \u003cSubmitButton /\u003e\n  }}\n/\u003e\n```\n\n…or an array that will be used to pair area/line names with the `children`\npassed to `Layout`:\n\n```jsx\n\u003cLayout rows={['header', 'body', 'footer']}\u003e\n  \u003cTitle\u003eLeave a comment\u003c/Title\u003e\n  \u003cTextInput /\u003e\n  \u003cSubmitButton /\u003e\n\u003c/Layout\u003e\n```\n\nHow you define the actual layout of the areas/columns/rows depends on your\nstyling solution. Examples follow.\n\n### …with [styled-components][]\n\n`Layout` and its children receive their styling from `className`. Define the\ngrid layout using `styled()`:\n\n```jsx\nimport styled from 'styled-components'\nimport Layout from 'layup/styled'\n\nconst FoodLayout = styled(Layout)`\n  grid-template-areas:\n    'pizza .     .    '\n    '.     tacos .    '\n    '.     .     ramen';\n`\n\n\u003cFoodLayout areas={{\n  pizza: \u003cPizza /\u003e,\n  tacos: \u003cTacos /\u003e,\n  ramen: \u003cRamen /\u003e\n}} /\u003e\n```\n\n### …with [Emotion][]\n\n`Layout` and its children receive their styling from `className`. Either use\n`styled()` (see the styled-components example above) or define the grid layout\nusing `css`:\n\n```jsx\nimport { css } from 'emotion'\nimport Layout from 'layup/emotion'\n\nconst foodLayout = css`\n  grid-template-areas:\n    'pizza .     .    '\n    '.     tacos .    '\n    '.     .     ramen';\n`\n\n\u003cLayout className={foodLayout} areas={{\n  pizza: \u003cPizza /\u003e,\n  tacos: \u003cTacos /\u003e,\n  ramen: \u003cRamen /\u003e\n}} /\u003e\n```\n\n### …with [glamor][]\n\n`Layout` and its children receive their styling from `className`. Define the\ngrid layout using `css`:\n\n```jsx\nimport { css } from 'glamor'\nimport Layout from 'layup/glamor'\n\nconst foodLayout = css({\n  gridTemplateAreas: `\n    'pizza .     .    '\n    '.     tacos .    '\n    '.     .     ramen'\n  `\n})\n\n\u003cLayout className={foodLayout} areas={{\n  pizza: \u003cPizza /\u003e,\n  tacos: \u003cTacos /\u003e,\n  ramen: \u003cRamen /\u003e\n}} /\u003e\n```\n\n### …with inline styles\n\nLayout receives its styling from `style`. Children must also support the `style`\nprop:\n\n```jsx\nimport Layout from 'layup/inline'\n\nconst foodLayout = {\n  gridTemplateAreas: `\n    'pizza .     .    '\n    '.     tacos .    '\n    '.     .     ramen'\n  `\n}\n\n\u003cLayout style={foodLayout} areas={{\n  pizza: \u003cPizza /\u003e,\n  tacos: \u003cTacos /\u003e,\n  ramen: \u003cRamen /\u003e\n}} /\u003e\n```\n\n### Adapting to any styling solution\n\nAll you need to do is define two components: Grid and Cell. Pass them to the\n`createLayout` function to get your Layout component.\n\n**Grid** should:\n\n* Render an element with `display: grid` styling pre-applied.\n* Render its `children`, which will be an array of Cell elements.\n* Apply any further styling received from Layout. This is how users will\n  customize the grid layout CSS.\n  * You can do this via a prop like `className` or `style`, for example – it\n    depends on your styling solution.\n\n**Cell** should:\n\n* Return a clone of its `child` prop using `React.cloneElement`. `child` will be\n  one of the components passed to Layout.\n  * Note that because it returns a clone, from the perspective of CSS, the\n    children passed to Layout _are_ the grid cells (they aren’t _wrapped by_\n    grid cells).\n* Apply `grid-area`, `grid-column`, or `grid-row` styling to the cloned child\n  based on the received `area`, `column`, or `row` prop, respectively.\n  * You can apply these styles via a prop like `className` or `style`, for\n    example – it depends on your styling solution. The only requirement is that\n    the child components must support that prop.\n\nSee the [styled-components adapter](src/styled.js) for an example.\n\n[styled system]: https://github.com/jxnblk/styled-system\n[styled-components]: https://www.styled-components.com/\n[emotion]: https://emotion.sh/\n[glamor]: https://github.com/threepointone/glamor\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexogen%2Flayup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexogen%2Flayup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexogen%2Flayup/lists"}