yoga-layout は様々な言語で動作するフレックスボックスのレイアウトエンジンです。これは JavaScript でも使えます。
Yoga Layout | A cross-platform layout engine
facebook/yoga: Yoga is a cross-platform layout engine which implements Flexbox. Follow https://twitter.com/yogalayout for updates.
JavaScript でのインストールは次の yoga-layout-prebuilt を用いて npm install yoga-layout-prebuilt
とした方が良いです。yoga-layout そのものからインストールをしようとした場合、ビルドに必要な周辺ツールが多く問題も起きやすいですが、この yoga-layout-prebuilt はあらかじめ JavaScript 向けのビルドが済んでおり、よくあるライブラリの様に npm install のみでインストールできます。
これを用いると CSS でdisplay: flex
として作れるフレックスボックスレイアウトを座標と大きさだけで表現できます。
具体的に何をしてくれるかというと次です。
ソースコード
import yoga from "yoga-layout-prebuilt"; const Node = yoga.Node; // フレックスボックスのルートになる箱の要素の生成 const rootNode = Node.create(); // 大きさの設定 rootNode.setWidth(170); rootNode.setHeight(97); // 内部要素と親要素に隙間を空けたいのでパディングを追加 rootNode.setPadding(yoga.EDGE_ALL, 5); // 内部の並び方を設定。CSSの display: flex から使うアレが一通りそろっています rootNode.setJustifyContent(yoga.JUSTIFY_SPACE_BETWEEN); rootNode.setAlignItems(yoga.ALIGN_CENTER); rootNode.setFlexWrap(yoga.WRAP_WRAP); rootNode.setFlexDirection(yoga.FLEX_DIRECTION_ROW); // フレックスボックス内部の要素の生成 const one = Node.create(); one.setWidth(60); one.setHeight(40); // 右側にマージンをつけるなど色々できます // one.setMargin(yoga.EDGE_RIGHT, 12); // フレックスボックス内部の要素の生成 const two = Node.create(); two.setWidth(60); two.setHeight(40); // フレックスボックス内部の要素の生成 const three = Node.create(); three.setWidth(60); three.setHeight(40); // 親子関係を生成 rootNode.insertChild(one, 0); rootNode.insertChild(two, 1); rootNode.insertChild(three, 2); // 配置を計算 rootNode.calculateLayout(500, 300, yoga.DIRECTION_LTR); // 計算結果。個々に配置と大きさが与えられます console.log(JSON.stringify(rootNode.getComputedLayout())); console.log(JSON.stringify(one.getComputedLayout())); console.log(JSON.stringify(two.getComputedLayout())); console.log(JSON.stringify(three.getComputedLayout())); // {"left":0,"right":0,"top":0,"bottom":0,"width":170,"height":97} // {"left":5,"right":0,"top":5,"bottom":0,"width":60,"height":40} // {"left":105,"right":0,"top":5,"bottom":0,"width":60,"height":40} // {"left":5,"right":0,"top":45,"bottom":0,"width":60,"height":40} // ↑を元に position: absolute と座標と大きさ指定でデザインを元にHTMLを描画 function layout2el(l) { const el = document.createElement("div"); el.style.top = l.top + "px"; el.style.left = l.left + "px"; el.style.width = l.width + "px"; el.style.height = l.height + "px"; el.style.position = "absolute"; el.style.border = "solid 1px #000"; return el; } const rootEl = layout2el(rootNode.getComputedLayout()); rootEl.style.position = "relative"; const oneEl = layout2el(one.getComputedLayout()); oneEl.innerText = "one"; const twoEl = layout2el(two.getComputedLayout()); twoEl.innerText = "two"; const threeEl = layout2el(three.getComputedLayout()); threeEl.innerText = "three"; rootEl.appendChild(oneEl); rootEl.appendChild(twoEl); rootEl.appendChild(threeEl); document.getElementById("app").appendChild(rootEl);
ぱっと見よくあるフレックスボックスレイアウトですが、次のスクリーンショットからわかる様に位置と大きさを直接指定してデザインを構成しています。この様に yoga-layout を使うとフレックスボックスレイアウトをブラウザのレンダリングエンジン抜きで作れます。
この座標によるレイアウトの作り方は普通の web ページ上ではメリットがありませんが、そうではない時に便利です。これは例えば canvas 要素や pdf-lib による PDF の生成・編集などが挙げられます。
この記事では yoga-layout を紹介しましたが JavaScript のライブラリにはレイアウトエンジンがそれなりにあります。これは恐らくブラウザゲームなどで canvas を使ってなんやかんや座標直指定の出番があるからかだと思います。フレックスボックス以外にもグリッドであったりゲームでよくあるUIであったり何なりと色々あるので、そういったものが必要な時には探してみるのも良さそうです。