• Stars
    star
    190
  • Rank 198,931 (Top 4 %)
  • Language
  • License
    Other
  • Created over 6 years ago
  • Updated over 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Embeddable layout engine. Like flexbox, but with fewer concepts, applied uniformly.

Subform Layout

Demonstration of various layouts

Edit this layout on Codepen

Subform is a visual tool for defining and exploring responsive designs. This is an embeddable version of its layout engine, which you might want to use if:

  • You want identical layouts across multiple platforms (Web, iOS, Android, etc.)
  • You need layout on a platform without any native facilities (e.g., OpenGL)
  • You're just tired of CSS

The demos and engine in this repo are free to use and modify for non-commercial use only. For commercial licensing and support, please contact us.

This repo contains a Web Assembly version of the Subform engine. The core engine knows nothing about the DOM, JavaScript, etc. Its internal API is a byte array, and the engine can be run incrementally, "off the main thread", and does not require a garbage collector.

If you'd like to use API directly, or try the engine on a different platform (iOS, Android, C, etc.), please contact us.

Plain JS Example

The render_to_canvas.js creates the layout seen above, which is defined via a tree of plain JavaScript objects:

{layout: {mode: "self-directed",
          horizontal: {size: width},
          vertical: {size: height}},

          childrenLayout: {mode: "grid",
                           rows: {beforeFirst: 10, between: 20, afterLast: 10},
                           cols: {beforeFirst: 10, between: 40, afterLast: 10, sizes: [50, "2s", "1s"]}},

          children: [{layout: {rowSpan: 2}},

                     {layout: {rowIdx: 0, colIdx: 1},
                      childrenLayout: {mode: "stack-horizontal",
                                       mainBeforeFirst: "1s",
                                       mainBetween: 10,
                                       mainAfterLast: "50%"},
                      children: [{}, {}, {}]},

                     {layout: {rowIdx: 1, colIdx: 2},
                      children: [{layout: {cross: {before: 0}}},
                                 {},
                                 {layout: {cross: {after: 0}}}]}]}

React.js demo

In the React.js example, nodes have layout and childrenLayout props:

var app = function(width, height){
  return React.createElement("div", {layout: {mode: "self-directed",
                                              horizontal: {size: width},
                                              vertical: {size: height}},
                                     childrenLayout: {mode: "stack-horizontal"}},

                             React.createElement("div"),
                             React.createElement("div", {layout: {main: {before: 20, size: 50, after: 20},
                                                                  cross: {before: 10, size: "1s", after: 10}}}),
                             React.createElement("div"));
};

subform_init_react_layout(function(render){
  render(app(400, 400), document.getElementById("container"));
});

React layout example

The provided render function takes a React component, walks it to extract these layout props, solves the layout, and then adds the CSS absolute positioning inline styles before calling ReactDOM.render to actually mount/update.

The developer experience is exactly the same as using inline CSS. (Except that, hopefully, layouts can be implemented without referring to css-tricks.com =P)

Layout semantics

Subform's layout semantics are similar to flexbox, but with fewer concepts, applied uniformly. See this article for an overview, or this talk for the original motivation and conceptual design process.

Here's the tl;dr:

  • All elements have a horizontal and vertical axis, each of which consists of space before, size, and space after.

  • Elements either control their own position ("self-directed", akin to CSS absolute positioning) or are positioned by their parent ("parent-directed").

  • Parents can position their parent-directed children in a vertical stack, horizontal stack, or grid.

  • The same units -- pixels, percentages (of the parent size), and stretch (akin to flex, proportionally dividing up available space) -- are used everywhere, with minimum and maximum constraints as part of the unit.

All fields are optional.

Reasons to consider Subform layout

  • You'd like to use a visual tool to explore and refine layout.

  • You'd like to use the same layout engine on multiple platforms.

  • You need more than simple pinning constraints, but don't want the complexity of CSS.

Why Subform layout might be a bad fit

  • You don't want to ship a layout engine with your application.

  • You have a workflow built around AutoLayout/Cassowary, CSS, or Photoshop comps that's working just fine.

Notes / Caveats

  • The subform_layout.js file is ~400kB because it contains the engine WASM encoded as base64 to workaround CORS limitations, in addition to various shims required for the demos. In a production toolchain, the engine can be substantially smaller.

  • The API shown in these examples is subject to change. In fact, I'd love to hear your ideas about that! I'm open to implementing both a more programmatic API (using data structures instead of strings like "1s") as well as a full on human-shorthand stringified version (defined via EBNF grammar, of course).

Alternatives

Projects in a similar space:

  • Facebook's Yoga is a "cross-platform layout engine which implements Flexbox".

  • @randrew's Layout is a "single-file library for calculating 2D UI layouts using stacking boxes".

  • @schibsted's Layout is a "framework for implementing iOS user interfaces using runtime-evaluated expressions for layout and XML template files. It is intended as a more-or-less drop-in replacement for Nibs and Storyboards, but offers a number of advantages".

More Repositories

1

c2

Declarative data visualization in Clojure(Script).
JavaScript
643
star
2

cljx

Write a portable codebase targeting Clojure/ClojureScript
Clojure
400
star
3

reflex

Automatic state propogation in ClojureScript
Clojure
186
star
4

zmq-async

Threadsafe Clojure core.async interface to ZeroMQ
Clojure
167
star
5

vagrant-ec2

Use the same chef to provision Vagrant VMs and EC2 instances
Ruby
166
star
6

sandboxtron

Shell
120
star
7

jetty7-websockets-async

Clojure core.async interface to Jetty7's websockets.
Clojure
107
star
8

cljs-d3

A ClojureScript façade for the D3 JavaScript DOM-manipulation library
Clojure
86
star
9

todoFRP

Functional reactive todo lists
JavaScript
81
star
10

singult

JavaScript Hiccup compiler
CoffeeScript
51
star
11

cljs-react-perf

Performance experiments w/ CLJS React libraries and techniques.
Clojure
40
star
12

json-tagged-literals

More palatable JSON serialization
CoffeeScript
40
star
13

c2-demos

Example C2 visualizations and applications
Clojure
37
star
14

svd2zig

Generate Zig API from SVD register definitions.
Zig
33
star
15

clj-liblinear

A Clojure wrapper for LIBLINEAR, a linear support vector machine library
Clojure
28
star
16

cassowary-coffee

CoffeeScript port of the Cassowary linear constraint solver
CoffeeScript
24
star
17

hicada

A cljs hiccup compiler that helps you be deliberate about runtime interpretation.
Clojure
20
star
18

touchtron

Rust touchpad / usb experiments
Rust
16
star
19

clojurescript-compiler-proposal

Request for comments on ClojureScript compiler interface updates
Clojure
14
star
20

cljs-chosen

ClojureScript interface to Harvest's Chosen <select> library
JavaScript
12
star
21

tidy-codebase-starter-kit

Shell
9
star
22

vomnibus

Assortment of useful geographic data, color schemes, &c.
Clojure
8
star
23

vcf

Genetic variant analysis tool.
JavaScript
8
star
24

YALL1

All your sparse bases are belong to us.
Objective-C
8
star
25

lorax

Provably efficient deep learning
Clojure
5
star
26

prote.cs

Compressed sensing based protein fold search
JavaScript
4
star
27

denizen-demo-compojure

Demo Clojure web app using Denizen for user management
Clojure
4
star
28

question-rust-inlining

A question about inlining and match vs lookup tables in Rust.
LLVM
4
star
29

Rliblinear

R interface to LIBLINEAR, a linear support vector machine library
C++
3
star
30

cljs-hiccup-inference

Minimal example repo of a CLJS Hiccup->React compiler w/ type inference
Clojure
3
star
31

question-rust-websocket

Rust
2
star
32

profile-cljs

Wherein I examine ClojureScript performance.
Clojure
2
star
33

splot

Rust
1
star
34

datomic-fuse-AOT

A hellscape of Clojure+Datomic lazy loading errors.
Clojure
1
star
35

eui

Rust
1
star