# Orbit CSS Framework > Orbit is a CSS framework for building radial and circular user interfaces. > It uses CSS trigonometric functions (cos, sin), the :has() selector, and CSS custom properties to position elements on circular orbits — no layout JavaScript needed. ## Documentation - Docs: https://zumerlab.github.io/orbit-docs - Repo: https://github.com/zumerlab/orbit - npm: @zumer/orbit - Version: 1.4.8 - License: MIT ## Quick Start CDN: ```html ``` npm: ```bash npm install @zumer/orbit ``` ```js import '@zumer/orbit/style' // CSS import '@zumer/orbit' // JS (registers web components + Orbit.resize) ``` ## What the JS file does - Registers `` custom element (SVG arc/wedge segments) - Registers `` custom element (SVG progress rings) - Exposes `window.Orbit` with the `.resize()` method for responsive layouts - If you only use CSS classes (no web components, no responsive resize), the JS is optional. ## Core Concept Orbit uses a solar-system metaphor. Everything revolves around a center point called the **gravity-spot**. Elements are placed on concentric rings (**orbits**) and positioned automatically using CSS trigonometry (cos/sin). The framework auto-distributes children evenly around each orbit using the `:has()` selector to count them. ## Mandatory HTML Structure ``` .bigbang > .gravity-spot > .orbit-N > .satellite > .capsule ``` Every Orbit layout MUST follow this exact nesting hierarchy. Skipping or misordering any level will break the layout and trigger CSS validation warnings (red dotted borders). - `.bigbang` — Root container (flex center, 100% width/height, 100vh when direct child of body) - `.gravity-spot` — Center point (0 width, holds all CSS variables, origin of coordinate system) - `.orbit-N` — A ring at radius level N (0–24). Higher N = larger radius. Invisible by default. - `.satellite` — An item placed on a ring (positioned via cos/sin transforms, up to 60 per orbit) - `.capsule` — Content wrapper inside satellite (counter-rotates so content stays upright) ## Additional Elements (placed directly inside .orbit-N, NOT inside .satellite) - `` — SVG arc/wedge segments (pie slices, gauge needles, text along arcs) - `` — SVG progress ring with background track - `.vector` — Tick marks / radial lines (up to 60 per orbit) - `.side` — Chord/tangent elements that form polygons ## Key CSS Custom Properties (set on .gravity-spot or .orbit-N) | Property | Default | Purpose | |---|---|---| | `--o-force` | `500px` | Base diameter of the entire system. MUST be pixels. | | `--o-force-ratio` | `1` | Responsive scaling multiplier (set by Orbit.resize()) | | `--o-from` | `0deg` | Starting angle. 0deg = 12 o'clock (top). | | `--o-range` | `360deg` | Total arc span (180 = semicircle, 270 = three-quarter) | | `--o-direction` | `1` | 1 = clockwise, -1 = counter-clockwise | | `--o-fit-range` | `0` | 1 = distribute items within range without overlap at boundaries | | `--o-size-ratio` | `1` | Multiplier for element sizes | | `--o-initial-orbit` | `0` | Offset added to orbit numbering (increases total orbits) | | `--o-ellipse-x` | `1` | Horizontal compression (>1 compresses). NOTE: o-arc/o-progress hidden when ≠ 1 | | `--o-ellipse-y` | `1` | Vertical compression (>1 compresses). NOTE: o-arc/o-progress hidden when ≠ 1 | | `--o-gap` | `1` | Gap between arc segments (for ``) | | `--o-orbit-ratio` | `0` | Shrinks spacing between orbits (0=normal, 1=all same size) | | `--o-aligment` | `0px` | Radial offset. Positive = inward, negative = outward | ## How Angle Auto-Distribution Works The framework counts children inside each orbit using CSS `:has(:nth-child(N of .satellite))` and automatically sets `--o-angle = --o-range / N`. Each child is positioned at `angle * child_index`. This means: - 4 satellites in a 360deg orbit → each at 90° apart - 3 arcs in a 270deg range → each at 90° apart - No manual angle calculation needed ## Utility Classes **Positioning:** `.at-top`, `.at-bottom`, `.at-center`, `.at-top-left`, `.at-top-right`, `.at-bottom-left`, `.at-bottom-right`, `.at-center-left`, `.at-center-right` **Range/Angle:** `.range-0` to `.range-360`, `.from-0` to `.from-360`, `.angle-0` to `.angle-360`, `.fit-range`, `.ccw` **Initial orbit:** `.from-1x` to `.from-12x` (on .gravity-spot, sets --o-initial-orbit) **Sizing:** `.shrink-0` to `.shrink-100` (step 5), `.grow-0.1x` to `.grow-12x` **Gap:** `.gap-0` to `.gap-30` (on ``) **Radial alignment:** `.inner-orbit`, `.quarter-inner-orbit`, `.quarter-outer-orbit`, `.outer-orbit` **Capsule modifiers:** `.flip`, `.turn-left`, `.turn-right`, `.horizontal` **Satellite shape:** `.circle`, `.box`, `.rounded-box`, `.spin-lock` **Effects:** `.gooey-fx-light`, `.gooey-fx-medium`, `.gooey-fx-max` (not Safari) ## Web Components ### `` — Arc/Wedge Segment Place directly inside `.orbit-N`. NEVER inside `.satellite`. - Attributes: `value` (0–100), `shape` (none|rounded|circle|circle-a|circle-b|bullet|arrow|slash|backslash|zigzag), `flip`, `fit-range`, `text-anchor` (start|middle|end) - CSS: `--o-fill`, `--o-stroke`, `--o-stroke-width`, `--o-color` - Text: `text here` renders text along the arc path - Stacking: Multiple `` with `value` attributes auto-stack end-to-end (donut chart). Values should sum to ≤ 100. - Without `value`: arcs auto-divide the range equally ### `` — Progress Ring Place directly inside `.orbit-N`. NEVER inside `.satellite`. Max one per orbit. - Attributes: `value` (number), `max` (default 100), `shape` (same as o-arc) - CSS: `--o-fill`, `--o-stroke`, `--o-stroke-width`, `--o-back-fill`, `--o-back-stroke`, `--o-back-stroke-width` ## Color System 10 base colors: `--o-red`, `--o-orange`, `--o-yellow`, `--o-green`, `--o-cyan`, `--o-blue`, `--o-indigo`, `--o-purple`, `--o-pink`, `--o-gray` Each has 6 variants: `-white`, `-lighter`, `-light`, `-dark`, `-darker`, `-black` Example: `--o-red-light`, `--o-cyan-darker` Dynamic: set `--o-color` on any element and use `--o-color-light`, `--o-color-dark`, etc. ## Themes - Default: transparent orbits, currentColor borders on satellites - `.theme-cyan`: cyan-colored borders and fills - `.dev-orbit`: red dashed borders on all elements (debugging) ## Responsive Sizing ```js Orbit.resize('.parent-selector'); ``` Calculates `--o-force-ratio = containerWidth / 500` using ResizeObserver. ## Critical Rules for LLMs 1. ALWAYS follow: `.bigbang > .gravity-spot > .orbit-N > .satellite > .capsule` 2. Put ALL visible content inside `.capsule`, never directly in `.satellite` 3. Use `.orbit-0 > .satellite.at-center > .capsule` for center content 4. `` and `` go directly in `.orbit-N`, NEVER in `.satellite` 5. `.vector` and `.side` go directly in `.orbit-N`, NEVER in `.satellite` 6. Multiple `.orbit-N` are siblings inside the same `.gravity-spot` 7. Do NOT nest `.orbit-N` inside another `.orbit-N`. For nested layouts, create `.bigbang > .gravity-spot` inside a `.capsule` 8. `--o-force` MUST be a pixel value (e.g., `500px`), never percentage 9. `.orbit-0` is just a center point (near-zero radius), not a visible ring 10. `from-0` = top/12 o'clock, NOT right/3 o'clock 11. `` and `` do NOT work in elliptical layouts 12. Do NOT use `transform` on `.satellite` — it overrides positioning 13. Do NOT set `--o-orbit-number`, `--o-orbit-child-number`, or `--o-angle` manually — these are auto-calculated 14. `.angle-N` resets `--o-from` to 0 — do NOT combine with `.from-N` on the same element (except on ``/`` where `.angle-N` does NOT reset `--o-from`) 15. Browser requirements: CSS :has(), CSS cos()/sin(), Web Components. No IE/old browser support. ## Nesting Pattern To create nested radial systems (planet with moons), use a new `.bigbang > .gravity-spot` inside a `.capsule`: ```html
Moon
``` ## Minimal Valid Example ```html
A
B
C
``` Places 3 items evenly (120° apart) on orbit ring 3. ## Optional: llms-full.txt For the complete API reference with all patterns, recipes, internal mechanics, and advanced examples, see [llms-full.txt](https://zumerlab.github.io/orbit-docs/llms-full.txt).