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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@simbafs/lx

v0.7.5

Published

HTML attribute DSL for absolute positioning

Readme

lx

lx is a lightweight, dependency-free JavaScript layout engine designed to define geometric relationships through HTML attributes and convert them into absolute CSS positioning coordinates. It is particularly suitable for web applications requiring precise positional control, complex dependency chains, or dynamic layout adjustments based on content.

Key Features

  • Declarative Geometric Syntax: Directly describe logic such as "my right edge is 10px from the left edge of Element A" in HTML.
  • Performance Optimization: Decouples layout into "Setup" (initialization) and "Update" (numerical refresh) to minimize the computational burden during window resizing or content changes.
  • Automatic Redraw: Includes lx-auto.js to automatically monitor window size, DOM structure, and content changes to trigger layout updates.
  • Solves Standard Layout Pain Points: Handles cross-container alignment needs that are difficult to achieve with standard CSS Flexbox or Grid.

Quick Start

Installation

Option 1: CDN (Recommended)

<script src="https://raw.githubusercontent.com/simbafs/lx/refs/heads/main/dist/lx.min.js"></script>
<script src="https://raw.githubusercontent.com/simbafs/lx/refs/heads/main/dist/lx-auto.min.js"></script>

Option 2: Download

Download lx.min.js and lx-auto.min.js from the dist folder and include them in your project.

Option 3: npm

npm install simbafs/lx

Basic Example

<div id="screen" lx lx-l="0" lx-t="0" lx-w="1920" lx-h="1080">
	<div id="sidebar" lx-r="body.right-20" lx-t="50" lx-w="300" lx-h="200/500">
		When this content changes, elements below move automatically.
	</div>

	<div id="content" lx-l="#sidebar.left" lx-r="#sidebar.right" lx-t="#sidebar.bottom+20" lx-h="100">
		Follower element
	</div>
</div>

Syntax Specification

1. Position Attributes

Supports lx-left (lx-l), lx-right (lx-r), lx-top (lx-t), and lx-bottom (lx-b).

  • Reference Mode: #id.edge[+/-offset] or body.edge[+/-offset].
  • Numeric Shorthand: If only a number is provided (e.g., lx-l="10"), it defaults to a 10px offset from the nearest lx container's edge.
  • Relative Selectors: Use previous.edge[+/-offset] or next.edge[+/-offset] to reference the logical previous or next sibling element within the same container. These are syntactic sugar that gets translated to concrete #id references during setup.

2. Size Attributes

Supports lx-width (lx-w) and lx-height (lx-h).

  • Fixed Size: Enter a number directly (e.g., 300).
  • Range Size: Use min/max syntax (e.g., 200/500). The element grows based on content while staying within these limits.
  • Expression: Use (expression) syntax (e.g., ({base}*2)).

3. Aspect Ratio

Supports lx-aspect (lx-a) to define width-to-height ratio.

<div id="video" lx-t="0" lx-l="0" lx-w="320" lx-a="16:9"></div>

This creates a video element with fixed width 320px and height calculated as 320 / (16/9) = 180px.

Constraint Rules: With lx-aspect, each dimension needs only one position reference plus the aspect ratio:

  • Horizontal Dominant: 2 horizontal constraints + 1 vertical reference + aspect
  • Vertical Dominant: 2 vertical constraints + 1 horizontal reference + aspect

Restrictions:

  • Cannot coexist with range sizes (e.g., 200/500)
  • Both W and H must be positive numbers

3. Variables & Math

Define reusable values with data-lx-* attributes and use them in expressions:

<body data-lx-gap="20" data-lx-scale="0.8">
  <div id="container" lx>
    <div id="sidebar" lx-l="#main.right+({gap}*2)" lx-t="50" lx-w="300" lx-h="500">
      Sidebar with gap spacing
    </div>
    <div id="content" lx-l="0" lx-t="#sidebar.bottom+({gap})" lx-w="100" lx-h="200">
      Content positioned with variable gap
    </div>
  </div>
</body>

Supported operators: +, -, *, /

Variable lookup: Variables bubble up from the current element to <body>. Child elements can override parent values.

Position expressions: Combine references with expressions like #id.edge+({gap}*2) or body.top-({offset}/2).

Dynamic updates: Changing any data-lx-* attribute automatically triggers lx.setup() to re-evaluate all expressions.

Note: All expressions are evaluated during setup() phase. Nested parentheses are not supported.

4. Constraint Rules

To ensure a unique solution, each element must satisfy one of these valid combinations:

  • Standard (no aspect): Two constraints per dimension
    • Horizontal: two from left, right, width
    • Vertical: two from top, bottom, height
  • With aspect ratio (lx-a): Cross-dimensional constraint
    • Horizontal dominant: 2 horizontal + 1 vertical + aspect
    • Vertical dominant: 2 vertical + 1 horizontal + aspect

Execution Mechanism

lx.js (Core Engine)

  1. setup(): Scans the DOM, parses attributes, builds a dependency graph, and detects circular dependencies.
  2. update(): When the structure is unchanged but values need refreshing (e.g., on resize), it uses the cached dependency graph for pure geometric calculations, skipping DOM scanning for better performance.

lx-auto.js (Automatic Monitoring)

Trigger updates in the following scenarios:

  • Window Resize: Listens to window.resize.
  • Content Change: Uses ResizeObserver to monitor physical size changes in range elements.
  • Structure/Text Change: Uses MutationObserver to monitor DOM additions/deletions, text modifications, or lx-* attribute changes. It automatically filters out style changes generated by the engine to prevent infinite loops.
  • Variable Change: Any data-lx-* attribute change triggers lx.setup() to re-evaluate all expressions.

Debug Mode

Add ?lx-debug to the URL to enable developer debug logs:

  • View parsed Canonical nodes.
  • Check the calculated dependency order.
  • Monitor reasons for each automatic redraw (e.g., resize, text-content-change).

License

MIT