{"id":13626508,"url":"https://github.com/lume/autolayout","last_synced_at":"2025-04-13T05:07:12.397Z","repository":{"id":41447843,"uuid":"369953018","full_name":"lume/autolayout","owner":"lume","description":"Apple's Auto Layout and Visual Format Language for JavaScript (using cassowary constraints)","archived":false,"fork":false,"pushed_at":"2024-09-17T18:36:25.000Z","size":1717,"stargazers_count":312,"open_issues_count":2,"forks_count":11,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-13T05:07:01.731Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/lume.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-05-23T03:35:47.000Z","updated_at":"2025-03-29T08:52:59.000Z","dependencies_parsed_at":"2023-11-25T15:42:49.539Z","dependency_job_id":null,"html_url":"https://github.com/lume/autolayout","commit_stats":{"total_commits":205,"total_committers":10,"mean_commits":20.5,"dds":"0.23414634146341462","last_synced_commit":"6d4f77a0cca9be8526a185ebeb85816e09e201fa"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lume%2Fautolayout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lume%2Fautolayout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lume%2Fautolayout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lume%2Fautolayout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lume","download_url":"https://codeload.github.com/lume/autolayout/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248665747,"owners_count":21142123,"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":[],"created_at":"2024-08-01T21:02:20.894Z","updated_at":"2025-04-13T05:07:12.379Z","avatar_url":"https://github.com/lume.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# @lume/autolayout\n\n\u003c!-- ![Logo](logo.png) --\u003e\n\nLUME AutoLayout implements Apple's [Auto Layout](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/index.html) and [Visual Format Language](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage.html) in Javascript (TypeScript), and will soon compile to WebAssembly via [AssemblyScript](http://assemblyscript.org/) for optimized layout calculation.\n\n\u003ch4\u003e\u003ccode\u003e\u003cstrong\u003enpm install @lume/autolayout\u003c/strong\u003e\u003c/code\u003e\u003c/h4\u003e\n\nAuto layout is a system which lets you perform layout using mathematical relationships (constraints). It uses the [LUME Kiwi](https://github.com/lume/kiwi) library to do the actual constraint resolving and implements Apple's constraint system and Visual Format Language (vfl) on top of that. It supports the [Extended VFL syntax](#extended-visual-format-language-evfl), including view-stacks and z-indexing.\n\n```js\n// Define the layout constraints using VFL syntax:\nvar constraints = AutoLayout.VisualFormat.parse(\n  [\n    'H:|[view1(==view2)]-10-[view2]|', // The horizontal aspect of the layout\n    'V:|[view1,view2]|', // The vertical aspect of the layout\n  ],\n  {extended: true},\n)\n\n// Create a view, uses the constraints to calculate the actual positioning and sizing of spaces in the layout:\nvar view = new AutoLayout.View({constraints: constraints})\nview.setSize(400, 500)\n\n// Access each space in the calculated layout:\nconsole.log(view.subViews.view1) // {left: 0, top: 0, width: 195, height: 500}\nconsole.log(view.subViews.view2) // {left: 205, top: 0, width: 195, height: 500}\n\n// Finally apply the layout to your rendering system. Autolayout is not coupled to any particular rendering system.\n\n// For example, position DOM elements where they should be:\nconst el1 = document.querySelector('.view1')\nel1.style.transform = `transform(${view.subViews.view1.left}px, ${view.subViews.view1.top}px)`\nel1.style.width = view.subViews.view1.width + 'px'\nel1.style.height = view.subViews.view1.height + 'px'\nconst el2 = document.querySelector('.view1')\nel2.style.transform = `transform(${view.subViews.view2.left}px, ${view.subViews.view2.top}px)`\nel2.style.width = view.subViews.view2.width + 'px'\nel2.style.height = view.subViews.view2.height + 'px'\n\n// Or if you're in WebGL using Three.js, then apply values to your meshes:\nmesh.postion.set(view.subViews.view2.left, -view.subViews.view2.top, 0)\nmesh.scale.set(view.subViews.view2.width, view.subViews.view2.height, 1)\n```\n\nLayouts can be previewed and debugged using the [Visual Format Editor](https://github.com/IjzerenHein/visualformat-editor):\n\n[![Example - click me](example.png)](https://rawgit.com/IjzerenHein/visualformat-editor/master/dist/index.html?vfl=example)\n_(click image to open the editor)_\n\n## Index\n\n- [Getting started](#getting-started)\n  - [Installation](#installation)\n  - [Using the API](#using-the-api)\n  - [API Documentation](#api-documentation)\n  - [Examples](#examples)\n- [Extended Visual Format Language (EVFL)](#extended-visual-format-language-evfl)\n- [Additional resources](#additional-resources)\n- [Benchmark](https://rawgit.com/lume/autolayout/master/bench/index.html)\n- [Tests](https://rawgit.com/lume/autolayout/master/test/index.html)\n- [Roadmap](#roadmap)\n- [Contribute](#contribute)\n\n## Getting started\n\nLUME AutoLayout is an abstract library for integrating Auto Layout and VFL into other javascript technologies. It provides a simple API and programming model that you can use to build your own auto layout and VFL solution. A simple example of this is, is using `position: absolute;` to [lay out DOM elements](https://rawgit.com/lume/autolayout/master/examples/DOM/index.html). A more elaborate example of this is the [Visual Format Editor](https://github.com/IjzerenHein/visualformat-editor), which is built using [famo.us](http://deprecated.famous.org) and [famous-flex](https://github.com/IjzerenHein/famous-flex).\n\n### Installation\n\nInstall using npm:\n\n    npm install autolayout\n\nInclude the library in your HTML project:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import AutoLayout from '//unpkg.com/@lume/autolayout@0.8.0/dist/AutoLayout.js?module'\n  // ...use AutoLayout here...\n\u003c/script\u003e\n```\n\nOr when using a bundler like Webpack or Rollup, or [import maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap), use:\n\n```js\nimport AutoLayout from '@lume/autolayout'\n// ...use AutoLayout here...\n```\n\nIf you're using import maps, f.e. in a browser without a build, or in a JS\nruntime like Deno, you'll need an importmap script that lists autolayout and its\ndependency kiwi. F.e.:\n\n```html\n\u003cscript type=\"importmap\"\u003e\n  {\n    \"imports\": {\n      \"@lume/autolayout\": \"/node_modules/@lume/autolayout/dist/AutoLayout.js\",\n      \"@lume/kiwi\": \"/node_modules/@lume/kiwi/dist/kiwi.js\"\n    }\n  }\n\u003c/script\u003e\n```\n\n### Using the API\n\nTo parse VFL into constraints, use:\n\n```javascript\ntry {\n  // The VFL can be either a string or an array of strings.\n  // strings may also contain '\\n' which indicates that a new line of VFL will begin.\n  var constraints = AutoLayout.VisualFormat.parse(['|-[child(==child2)]-[child2]-|', 'V:|[child(==child2)]|'])\n} catch (err) {\n  console.log('parse error: ' + err.toString())\n}\n```\n\nA View is the main entity onto which constraints are added. It uses the cassowary SimplexSolver to add\nrelations and variables. You can set the size of the view and other properties such as spacing. When constraints are added it automatically creates so called \"sub-views\" for every unique name that is encountered in the constraints. The evaluated size and position of these sub-views can be accessed through the `.subViews` property.\n\n```javascript\n// Create a view with a set of constraints\nvar view = new AutoLayout.View({\n  constraints: constraints, // initial constraints (optional)\n  width: 100, // initial width (optional)\n  height: 200, // initial height (optional)\n  spacing: 10, // spacing size to use (optional, default: 8)\n})\n\n// get the size and position of the sub-views\nfor (var key in view.subViews) {\n  console.log(key + ': ' + view.subViews[key])\n  // e.g. {\n  //   name: 'child1',\n  //   left: 20,\n  //   top: 10,\n  //   width: 70,\n  //   height: 80\n  // }\n}\n```\n\nBy changing the size, the layout is re-evaluated and the subView's are updated:\n\n```javascript\nview.setSize(300, 600)\n\n// get the new size \u0026 position of the sub-views\nfor (var key in view.subViews) {\n  console.log(key + ': ' + view.subViews[key])\n}\n```\n\nInstead of using VFL, you can also add constraints directly.\nThe properties are identical to those of [NSLayoutConstraint](https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class).\nTo constrain view1 to its parent view, use _null_ for view2.\n\n```\nview.addConstraint({\n    view1: 'child3',\n    attr1: 'width',    // see AutoLayout.Attribute\n    relation: 'equ',   // see AutoLayout.Relation\n    view2: 'child4',\n    attr2: 'width',    // see AutoLayout.Attribute\n    constant: 10,\n    multiplier: 1\n});\n```\n\n### API Documentation\n\n[The API reference documentation can be found here.](docs/AutoLayout.md)\n\n### Examples\n\n- [DOM Example](https://rawgit.com/lume/autolayout/master/examples/DOM/index.html) [(source)](examples/DOM)\n- [Visual Format Editor](https://github.com/IjzerenHein/visualformat-editor)\n- [react-autolayout](https://github.com/fattenap/react-autolayout)\n- [famous-autolayout](https://github.com/IjzerenHein/famous-autolayout)\n\n## Extended Visual Format Language (EVFL)\n\nApple's Visual Format Language prefers good notation over completeness of expressibility. Because of this some useful constraints cannot be expressed by \"Standard\" VFL. LUME AutoLayout defines an extended syntax (superset of VFL) which you opt-in to use. To enable the extended syntax, set option `extended` to `true` when parsing the visual format:\n\n```javascript\nvar evfl = '|-[view1(==50%)]'\nvar constraints = AutoLayout.VisualFormat.parse(evfl, {extended: true})\n```\n\n### Language features\n\n- [Proportional size](#proportional-size) (`|-[view1(==50%)]`)\n- [Operators](#operators) (`|-[view1(==view2/2-10)]-[view2]-|`)\n- [Attributes](#attributes) (`V:|[view2(view1.width)]`)\n- [Z-ordering](#z-ordering) (`Z:|-[view1][view2]`)\n- [Equal size spacers/centering](#equal-size-spacers--centering)(`|~[center(100)]~|`)\n- [View stacks](#view-stacks) (`V:|[column:[header(50)][content][footer(50)]]|`)\n- [View ranges (spread operator)](#view-ranges-spread-operator) (`H:[view1..8(10)]|`)\n- [Multiple views](#multiple-views) (`Z:|[background][text1,text2,text3]|`)\n- [Multiple orientations](#multiple-orientations-fill-content) (`HV:|[background]|`)\n- [Disconnections (right/bottom alignment)](#disconnections-rightbottom-alignment) (`|[view1(200)]-\u003e[view2(100)]|`)\n- [Negative values (overlapping views)](#negative-values-overlapping-views) (`|[view1]-(-10)-[view2]|`)\n- [Explicit constraint syntax](#explicit-constraint-syntax) (`C:view1.centerX(view2.centerX)`)\n- [Comments](#comments) (`[view1(view1.height/3)] // enfore aspect ratio 1/3`)\n\n### Proportional size\n\nTo make the size proportional to the **size of the parent**, you can use the following % syntax:\n\n    |-[view1(==50%)]    // view1 is 50% the width of the parent (regardless of any spacing)\n    [view1(\u003e=50%)]      // view1 should always be more than 50% the width of the parent\n\n### Operators\n\nOperators can be used to create linear equations of the form:\n`view1.attr1 \u003crelation\u003e view2.attr2 * multiplier + constant`.\n\nSyntax:\n\n    (view[.{attribute}]['*'|'/'{value}]['+'|'-'{value}])\n\nTo, for instance, make the width or height proportional to **another view**, use:\n\n    |-[view1(==view2/2)]-[view2]-|  // view1 is half the width of view2\n    |-[view1(==view2*4-100)]-[view2]-|  // view1 is four times the width minus 100 of view2\n\n### Attributes\n\nIn some cases it is useful to for instance make the **width equal to the height**. To do this you can\nuse the `.{attribute}` syntax, like this:\n\n    |-[view1]-|\n    V:|-[view1(view1.width)]\n\nYou can also combine with operators to for instance enforce a certain **aspect ratio**:\n\n    V:|-[view1(view1.width/3)]\n\nSupported attributes:\n\n    .width\n    .height\n    .left\n    .top\n    .right\n    .bottom\n    .centerX\n    .centerY\n\n### Z-Ordering\n\nWhen sub-views overlap it can be useful to specify the z-ordering for the sub-views:\n\n    Z:|[child1][child2]  // child2 is placed in front of child1\n    Z:|[background]-10-[child1..2]  // child1 and child2 are placed 10 units in-front of background\n\nBy default, all sub-views have a z-index of `0`. When placed in front of each other, the z-index\nwill be `1` higher than the sub-view it was placed in front of. The z-index of the sub-view can\nbe accessed through the `zIndex` property:\n\n    console.log('zIndex: ' + view.subViews.child2.zIndex);\n\n### Equal size spacers / centering\n\nSometimes you just want to center a view. To do this use the `~` connector:\n\n    |~[view1(100)]~|        // view1 has width of 100 and is centered\n    V:|~(10%)~[view2]~|     // top \u0026 bottom spacers have height of 10%\n\nAll `~` connectors inside a single line of EVFL are constrained to have the same size.\nYou can also use more than 2 connectors to proportionally align views:\n\n    |~[child1(10)]~[child2(20)]~[child3(30)]~|\n\n### View stacks\n\nView stacks make it possible to group views into a column or a row.\nThe following example creates a view stack named `column` which contains three sub-views. The benefit of this is revealed in the second line, in which the stack as a whole is horizontally positioned.\n\n    V:|[column:[top(50)][content][bottom(50)]]|\n    H:|[column]|\n\n### View ranges (spread operator)\n\nView ranges make it possible to select multiple views at once and apply rules for them:\n\n    //shapes circle1..5:circle\n    H:[circle1(circle1.height)] // set aspect-ratio for circle1\n    HV:[circle2..5(circle1)]    // use same width/height for other circles\n    H:|[circle1]-[circle2]-[circle3]-[circle4]-[circle5]|\n    V:|~[circle1..5]~|          // center all circles vertically\n\n### Multiple views\n\nSimilar to 'View ranges', multiple views can be separated using the `,` character:\n\n    H:|[left(top,right)]-[top,bottom]-[right]|\n    V:|[left,right]|\n    V:|[top(bottom)]-[bottom]|\n\n### Multiple orientations (fill content)\n\nSometimes you just want to fill a view to its container. With standard VFL you have to write two lines, one for the horizontal orientation and one for vertical:\n\n    H:|[background]|\n    V:|[background]|\n\nWith Extended VFL, these can be combined into one line:\n\n    HV:|[background]|\n\nWhen using spacers, you can even use different spacings for horizontal \u0026 vertical orientations:\n\n    //spacing: [10, 20]\n    HV:|-[background]-|\n\n### Disconnections (right/bottom alignment)\n\nBy default, views are interconnected when defined after each other (e.g. `[view1][view2][view3]`). In some cases\nit is useful to not interconnect the views, in order to align content to the right or bottom. The following\nexample shows a disconnection causing the content after the disconnect to align to the right-edge:\n\n```\n // left1..2 are left-aligned, right1..2 are right aligned\n      |[left1(100)][left2(300)]-\u003e[right1(100)][right2(100)]|\n      ^^                       ^^                         ^^\n   left1 is                 left2 and                  right2 is\n connected to               right1 are                connected to\n  super-view               not connected               super-view\n```\n\n### Negative values (overlapping views)\n\nNumbers and percentages can also be negative, which can be useful for overlapping views:\n\n    H:|[top,middle,bottom]|\n    V:|[top(100)]-(-10)-[middle(top)]-(middle/-2)-[bottom]|\n    Z:|[top][middle][bottom]\n\n### Explicit constraint syntax\n\nConstraints can also be expressed explicitly. This can be particularly useful\nwhen it is otherwise not possible to express a layout or rule:\n\n    C:view1.centerX(view2.centerX)     // view1 is horizontally centered to view2\n    C:view1.centerX(view2)             // attribute is inferred when omitted (centerX)\n    C:view1.centerX(view2).bottom(view2.bottom) // chaining syntax\n    C:view1.height(view2.width*2+10)   // expressions\n\n### Comments\n\nSingle line comments can be used to explain the VFL or to prevent its execution:\n\n    // Enfore aspect ratios\n    [view1(view1.height/3)] // enfore aspect ratio 1/3\n    // [view2(view2.height/3)] \u003c-- uncomment to enable\n\n## Additional resources\n\n- [Apple's Auto Layout](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/index.html)\n- [Visual Format Language](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage.html)\n- [Cassowary.js](https://github.com/slightlyoff/cassowary.js)\n- [Kiwi](https://github.com/lume/kiwi) (Fast TypeScript re-implementation of cassowary constraint solver)\n- [Overconstrained](http://overconstrained.io)\n- [Visual Format Editor](https://github.com/IjzerenHein/visualformat-editor)\n- [famous-autolayout](https://github.com/IjzerenHein/famous-autolayout)\n- [famous-flex](https://github.com/IjzerenHein/famous-flex)\n\n## Roadmap\n\nLUME AutoLayout is pretty close to feature complete. The existing features have\nbeen battle tested in several production environments and can be considered safe for production use.\n\nThe following features are still on the todo-list. Any help on making this\nfeature complete is very welcome:\n\n- [ ] Checking for ambigous layout.\n- [ ] Get constraint definitions from `View`\n- [ ] LTR (left to right reading) (Attribute.LEADING \u0026 Attribute.TRAILING)\n- [ ] Baseline support?\n  \u003c!-- - [ ] Remove constraints? --\u003e\n  \u003c!-- - [ ] DOM layouting primitives --\u003e\n\n## Contribute\n\nIf you like this project and want to support it, show some love and give it a\nstar, try it and report any bugs, write new feature ideas, or even\nopen a pull request!\n\nAlso have a look at [CONTRIBUTING](./CONTRIBUTING.md).\n\n## License\n\n© 2015 Hein Rutjes\n© 2021 Joseph Orbegoso Pea (http://github.com/trusktr)\n© 2021 Lume\n\n[![License](http://img.shields.io/:license-mit-blue.svg)](https://tldrlegal.com/license/mit-license)\n\n\u003c!--\nTODO\n\n## Status\n\n[![Build Status](https://travis-ci.org/IjzerenHein/autolayout.js.svg?branch=master)](https://travis-ci.org/IjzerenHein/autolayout.js)\n[![view on npm](http://img.shields.io/npm/v/autolayout.svg)](https://www.npmjs.org/package/autolayout)\n\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flume%2Fautolayout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flume%2Fautolayout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flume%2Fautolayout/lists"}