AppDimens

May 13, 2026 · View on GitHub

AppDimens — responsive sizing across phones, foldables, tablets, TVs, and the web

AppDimens — Smart Responsive Dimensions for Any Screen

A family of responsive sizing libraries that replaces fragile dp / sp / pt / px with explicit, perceptual scaling kernels — same vocabulary, same math, across Android, Apple, KMP, Flutter, React Native and the Web.

Repo License Platforms Scaling modes Contributions welcome

Read the docs Practical guide Examples

Platform repositories (quick reference)

Each implementation lives in its own GitHub repository (not only the submodules in this hub). Status reflects the current product line described in that repo’s README.

RepositoryPlatformStatus
appdimens-dynamicAndroid — Jetpack Compose, Kotlin Views, Java ViewsProduction
appdimens-sdpsAndroid — XML @dimen SDP-style resources (+ Compose tokens)Production
appdimens-sspsAndroid — XML SSP-style text resources (+ Compose tokens)Production
appdimens-gamesAndroid — game / NDK sizing helpersWork in progress
appdimens-iosApple — iOS / iPadOS / macOS (UIKit, SwiftUI, Metal)Work in progress
appdimens-dynamic-kmpKotlin MultiplatformWork in progress
appdimens-flutterFlutter — Android, iOS, Web, desktopWork in progress
appdimens-react-nativeReact Native — iOS & AndroidWork in progress
appdimens-webWeb — vanilla JS, React, Vue, Svelte, AngularWork in progress

Details, coordinates, and semver: see Platform matrix below.

Tip

TL;DR — Plain dp / sp / pt / px factor out density but not canvas extent or aspect ratio. AppDimens models token sizing as a family of one-dimensional maps with explicit kernels (linear, hybrid linear–logarithmic, Weber–Fechner, Stevens, fluid clamp, geometric, letterbox/fill, density buckets, constraint-based resize) and gives you the same vocabulary on every platform so a 16.sdp on Android Compose, a balanced(16) on iOS / Flutter / React Native, and a webdimens.balanced(16) on the Web all describe the same idea.

This repository is the documentation hub. Each platform library ships from its own submodule with its own semver, install line, and changelog. The hub never pins versions — always confirm the install line in the submodule README you depend on.


Table of contents

  1. Platform repositories (quick reference)
  2. What is AppDimens?
  3. The problem it solves
  4. How AppDimens solves it
  5. Why AppDimens (advantages)
  6. When to use AppDimens (scenarios)
  7. The 14 scaling kernels at a glance
  8. Quick start (multi-stack)
  9. Platform matrix
  10. Hub vs submodules — who owns what
  11. Documentation map (DOCS/)
  12. Performance snapshot
  13. Comparison with alternatives
  14. FAQ
  15. Roadmap & status
  16. Contributing, security, license
  17. Author

What is AppDimens?

AppDimens is a multi-platform family of responsive sizing libraries. You write a single base value at the call-site — 16.sdp, balanced(16), webdimens.balanced(16) — and the library transforms it through an explicit, named kernel that reflects the current screen Configuration (width, height, aspect ratio, density, orientation, multi-window flags, fold state).

The hub publishes the shared vocabulary (BALANCED, DEFAULT, PERCENTAGE, …) and the mathematical reference for every kernel. Each platform repository (appdimens-dynamic, appdimens-sdps, appdimens-ssps, appdimens-ios, appdimens-dynamic-kmp, appdimens-flutter, appdimens-react-native, appdimens-web, appdimens-games) implements that vocabulary natively, so design tokens travel across stacks without translation.

Two operating tracks coexist:

  • Runtime computation (appdimens-dynamic, iOS, Flutter, RN, Web, KMP): a tiny kernel runs at call time, reading the live Configuration and producing a Dp / point / px value through the chosen strategy. Lock-free padded cache keeps hot-path cost at roughly 5 ns per hit on a Snapdragon 888, ~1 ns on JVM (see Performance snapshot).
  • Pre-computed resources (appdimens-sdps, appdimens-ssps): thousands of pre-calculated @dimen/_*sdp, @dimen/_*ssp, _*hdp, _*wdp resources, ready to drop into XML — zero-runtime sizing for view systems and Compose alike.

You can — and many teams do — combine both.


The problem it solves

Modern UIs ship on a moving target. The same code base must look right on:

Form factorTypical width (dp / pt)What "48 looks like" with raw dp/sp/pt
Watches< 24048 covers ~20% of the screen — too dominant
Small phones320–360~14–15% — the calibrated baseline
Phablets / regular phones360–48010–13% — already drifting
Small tablets600–7206.7% — visibly cramped
Large tablets / foldables (open)720–9605–6% — clearly undersized
TVs960–1920+2.5–5% — practically invisible
Web / desktop viewports1024–3840+< 2% — broken

dp / sp factor out physical density but not canvas extent, and they are blind to aspect ratio (a 4:3 tablet and a 21:9 phone receive the same number). Naïve linear scalers like SDP fix the smallness on tablets only to produce oversized UI on the same TVs.

Concretely, for a 48 dp button:

ApproachPhone (360 dp)Tablet (720 dp)TV (1080 dp)Verdict
Raw dp / sp48 dp (13%) ✅48 dp (6.7%) ❌ tiny48 dp (4.4%) ❌ invisibleDensity-only
Linear SDP / SSP58 dp (16%) ✅115 dp (16%) ❌ huge173 dp (16%) ❌ enormousOver-scales
AppDimens auto (BALANCED)58 dp (16%) ✅~70 dp (10%) ✅~85 dp (8%) ✅Calibrated everywhere

The 720 dp / 1080 dp rows above are reproducible from DimenAutoDp (auto.md, hinge at 480 dp, ln gain 0.4).


How AppDimens solves it

flowchart LR
  concept["Hub concept<br/>(BALANCED · DEFAULT · PERCENTAGE · …)"] --> submodule["Submodule kernel<br/>(scaled · auto · percent · …)"]
  submodule --> token["Stack token<br/>(16.sdp · 16.asdp · balanced(16) · …)"]
  token --> output["Output Dp / Pt / Px<br/>(Configuration-aware)"]

Token sizing is modeled as a family of one-dimensional maps

f_S : (b, c) ↦ f_S(b, c)

where b is the design-time base (a dp / sp) and c is a snapshot of the runtime Configuration (post orientation/multi-window plumbing). S selects a kernelscaled, auto, percent, power, logarithmic, fluid, interpolated, diagonal, perimeter, fit, fill, density, resize, or NONE.

Every kernel obeys four invariants (THEORY.md §1.2):

  1. Reference fixed point. f_S(b, c₀) = b on the calibrated reference canvas — your design comp size is preserved on the reference device.
  2. Monotone in canvas extent. Bigger canvas ⇒ never smaller output.
  3. Bounded growth. Output is sandwiched between linear and logarithmic envelopes — no runaway tablets/TVs.
  4. Aspect-ratio aware (opt-in). The optional a suffix folds in an AR multiplier referenced to 16:9.

The verified constants (cross-checked against DesignScaleConstants.kt):

ConstantValueMeaning
BASE_WIDTH_DP300fReference width denominator (matches the 300 dp design-comp tradition)
BASE_HEIGHT_DP533fCompanion height baseline
REFERENCE_ASPECT_RATIO1.78fNeutral AR (16:9) — multiplier is 1 here
Diagonal baseline√(300² + 533²) ≈ 611.63 dpFor diagonal kernel
Perimeter baseline833 dpFor perimeter kernel
auto hingemeasured axis 480 dpBALANCED switches from linear to log here
auto ln gain0.4fLog damping coefficient

For the full math, see DOCS/THEORY.md and the canonical MATHEMATICS-AND-CALCULUS.md inside appdimens-dynamic.


Why AppDimens (advantages)

Each bullet below either points to a verifiable file in this repository or a measurable constant.

Engineering

  • Explicit kernels per call-site. No surprise behaviour — 16.sdp is always the scaled kernel and 16.asdp is always the auto kernel. The Kotlin extension you write is the formula you read. (COMPOSE-API-CONVENTIONS.md)
  • Zero-XML option. Pure code-driven sizing via appdimens-dynamic. Or pre-baked @dimen resources via appdimens-sdps / appdimens-ssps when you want XML tooling and zero-runtime cost.
  • Sub-microsecond hot path. Padded, sharded, lock-free cache. ~5 ns cache hit, ~2 ns raw multiply (Snapdragon 888 hardware capture, see appdimens-dynamic/PERFORMANCE.md).
  • Foldable & multi-window aware. Effective-axis selection consults WindowManager fold state and isInMultiWindowMode. Both behaviours are opt-out per call via the i / ia suffixes (THEORY.md §3).
  • R8 / ProGuard ready. AARs ship consumer-rules.pro and res/raw/keep.xml so apps can use minifyEnabled, R8 full mode (android.enableR8.fullMode=true), and shrinkResources without extra rules. See appdimens-dynamic/R8-PROGUARD.md.
  • Test- and preview-friendly. Kernels are pure functions of (base, Configuration) — works identically inside @Preview, unit tests, and BoxWithConstraints.

Design

  • Perceptual scaling. Not just proportional — kernels like auto, logarithmic, power damp growth on large canvases the way human visual perception expects (Weber–Fechner, Stevens). (THEORY.md §5)
  • Aspect-ratio compensation, opt-in. The a suffix folds an AR multiplier referenced to 16:9. Elongated phones / foldables / wide TVs keep their visual weight without bespoke remember blocks.
  • Orientation inverters. Authored portrait but the device rotates? The *Ph, *Lw, *Lh token families switch the driving axis automatically. (DOCS/ORIENTATION.md)
  • Physical units (mm / cm / inch). Real-world measurements where they matter (kiosks, AR, accessibility hit targets). (physical-units.md)

Ecosystem

  • Six platform tracks under one vocabulary — see Platform matrix. Android Compose + XML, Apple (UIKit + SwiftUI), Kotlin Multiplatform, Flutter, React Native, Web (vanilla / React / Vue / Svelte / Angular), and a games surface with Android NDK + iOS Metal.
  • Compose 3.x package split. Each kernel is its own Gradle source package (compose.scaled, compose.auto, compose.percent, …). You import what you use and nothing else — the binary footprint stays small.

Maintenance & honesty

  • Every kernel is cited to a Kotlin file under appdimens-dynamic/DOCUMENTATION/ and a regression test under appdimens-dynamic/library/.
  • Hub theory is reproducible. Numerical comparisons in DOCS/THEORY.md §8 come from the same kernels you ship.
  • No marketing-rank claims. The hub does not pretend a single global "best library" ranking. Categorical trade-offs vs other tools are discussed honestly in Comparison with alternatives.

When to use AppDimens (scenarios)

ScenarioWhy AppDimens helpsSuggested entry point
Multi-form-factor product (phones + tablets + foldables in one binary)auto (BALANCED) keeps the same UI calibrated on a 360 dp phone and a 720 dp tablet, without the SDP overshootappdimens-dynamic quick start → tokens asdp / assp
TV / large-screen companion applogarithmic and auto damp growth on canvases beyond 480 dp instead of inflating linearlylogarithmic.md · auto.md
Cross-platform design systemSame vocabulary on Android / iOS / KMP / Flutter / RN / Web — design tokens travel verbatimDOCS/PLATFORMS.md
XML view system with breakpoint resources@dimen/_16sdp, _18ssp, _300wdp, … shipped pre-computed; no runtime costappdimens-sdps · appdimens-ssps
Typography with hard min/max boundsfluid clamps a typographic band (e.g. 16–24 sp between 320–768 dp) the same way CSS clamp() would, with optional ARfluid.md
Game UI / HUD on arbitrary viewportsfit (letterbox) and fill (cover) keep the HUD intact across aspect ratiosfit.md · fill.md
Native game rendering (NDK / Metal)Specialized modules with C++/NDK on Android (appdimens-games) and Metal on iOSappdimens-games/
Real-world physical sizing (kiosks, AR, accessibility targets)mm / cm / inch helpers on every stackphysical-units.md
Rotation- / foldable-sensitive layoutsBase-orientation + *Ph / *Lw / *Lh invertersDOCS/ORIENTATION.md
Container-fit titles / square widgetsresize builders (autoResizeTextSp, autoResizeSquareSize) pick the largest size in a min..max range that still fitsresize.md

When AppDimens is overkill — single-form-factor prototypes with rigid hand-tuned mockups, or marketing microsites already handled by CSS clamp() / media queries.


The 14 scaling kernels at a glance

Sourced from appdimens-dynamic/DOCUMENTATION/ and cross-checked in DOCS/THEORY.md §5 and DOCS/PLATFORMS.md. Tokens shown are Compose 3.x; iOS / Flutter / RN / Web use builder names — see PLATFORMS.md.

#KernelHub labelCompose token sketchPrimary use caseReference
1scaledDEFAULT / FIXEDsdp, hdp, wdp, ssp, sem, sdpaPhone-first SDP-style baseline (most common)scaled.md
2autoBALANCEDasdp, ahdp, awdp, asspMulti-device hybrid (linear under 480 dp, logarithmic above)auto.md
3percentPERCENTAGE / DYNAMICpsdp, phdp, pwdp, plus literal space* percentagesAxis-heavy / proportional containers and gridspercent.md
4powerStevens-stylepwsdp, pwsspConfigurable sublinear curve (exponent 0.6–0.9)power.md
5logarithmicWeber–Fechnerlogsdp, logsspMaximum damping on TV / very large tabletslogarithmic.md
6fluidClamp bandfsdp, fsspTypography / spacing between explicit min/maxfluid.md
7interpolatedFixed–linear blendisdp, isspModerate scaling (50% linear / 50% fixed)interpolated.md
8diagonalEuclideandsdp, dsspScale by screen diagonal (true physical feel)diagonal.md
9perimeterpsdp (perimeter package), psspScale by W + H perimeterperimeter.md
10fitLetterboxfitsdp, fitsspGame / canvas content that must not cropfit.md
11fillCoverfillsdp, fillsspGame / canvas content that must fillfill.md
12densityDPI-bucketdensdp, densspScale only when the dpi bucket changesdensity.md
13resizeConstraint geometryautoResizeTextSp, autoResizeSquareSize, ResizeBoundPick the largest size in a min..max range that fitsresize.md
14physical unitsReal-world10.mm, 8.cm, 5.inchReal-world measurements (kiosks, AR, accessibility)physical-units.md

Plus a conceptual NONE (raw Dp / Sp) for surfaces that must stay constant.

Aspect-ratio suffix. Append a to scaled / auto / interpolated / logarithmic / power tokens (16.sdpa, 16.asdpa, 16.sspa, 16.assp) to fold in the AR multiplier described in THEORY.md §4. Append i / ia to opt out of the multi-window heuristic. The fluid package exposes AR as an explicit builder parameter instead.


Quick start (multi-stack)

Install lines below are illustrative. The authoritative semver line for every artifact lives in the submodule README — click through before pinning.

Android — Jetpack Compose (appdimens-dynamic, production)

import com.appdimens.dynamic.compose.*

Box(
    Modifier
        .padding(16.sdp)       // scaled — SDP-style baseline
        .width(100.wdp)        // scaled — width axis
        .height(48.hdp)        // scaled — height axis
) {
    Text("Hello", fontSize = 16.ssp)
    // For the hybrid BALANCED curve, use the `auto` tokens:
    // padding(16.asdp), fontSize = 16.assp
}

appdimens-dynamic/README.md#quick-start--scaled-compose for full install line and AppDimensProvider setup.

Android — XML resources (appdimens-sdps + appdimens-ssps, production)

<TextView
    android:layout_width="@dimen/_300sdp"
    android:layout_height="wrap_content"
    android:padding="@dimen/_16sdp"
    android:textSize="@dimen/_18ssp"
    android:text="Hello" />

appdimens-sdps/README.md · appdimens-ssps/README.md.

iOS — SwiftUI (appdimens-ios, work in progress)

Text("Hello")
    .font(.system(size: AppDimens.shared.balanced(16).toPoints()))
    .padding(AppDimens.shared.balanced(16).toPoints())
    .frame(width: AppDimens.shared.balanced(300).toPoints())

appdimens-ios/ for current install status.

Kotlin Multiplatform (appdimens-dynamic-kmp, work in progress)

KMP test line publishes under the same Maven artifact ID; do not mix blindly with Android 3.1.x. The KMP track is aiming at its first stable 1.0.0 and is documented inside appdimens-dynamic-kmp/.

Flutter (appdimens-flutter, work in progress)

Container(
  width: AppDimens.fixed(300).calculate(context),
  padding: EdgeInsets.all(AppDimens.fixed(16).calculate(context)),
  child: Text(
    'Hello',
    style: TextStyle(fontSize: AppDimens.fixed(16).calculate(context)),
  ),
)

appdimens-flutter/.

React Native (appdimens-react-native, work in progress)

{% raw %}

const { balanced } = useAppDimens();

return (
  <View style={{ padding: balanced(16) }}>
    <Text style={{ fontSize: balanced(16) }}>Hello</Text>
  </View>
);

{% endraw %}

appdimens-react-native/.

Web — webdimens (work in progress)

import { webdimens } from 'webdimens';

document.getElementById('title')!.style.fontSize = webdimens.balanced(24);
document.getElementById('container')!.style.padding  = webdimens.balanced(16);

appdimens-web/ for framework-specific (React / Vue / Svelte / Angular) hooks.


Platform matrix

Each folder below is its own Git submodule. Always confirm semver in the submodule README before pinning.

SubmodulePlatformWhat it shipsStatusIllustrative coordinate
appdimens-dynamic/Android (Compose, Kotlin, Java)Runtime kernels — all 14 scaling modes (12 strategies + Resize + Physical units)Productionio.github.bodenberg:appdimens-dynamic:3.1.5
appdimens-sdps/Android (XML, Compose, Kotlin, Java)Pre-computed @dimen/_*sdp / _*hdp / _*wdp resources + Compose tokensProductionio.github.bodenberg:appdimens-sdps:3.1.2
appdimens-ssps/Android (XML, Compose, Kotlin, Java)Pre-computed @dimen/_*ssp text resources + Compose tokensProductionio.github.bodenberg:appdimens-ssps:3.1.2
appdimens-games/Android (Kotlin + C++/NDK + OpenGL ES)Specialized game-loop dimension types, Vector2D / Rectangle, viewport modesWork in progressio.github.bodenberg:appdimens-games:2.0.1
appdimens-ios/iOS / macOS (UIKit + SwiftUI + Metal)AppDimens.shared.balanced(_) / defaultScaling(_) / smart(_) / fluid + Metal gamesWork in progressCocoaPods 2.0.0 / SPM (see submodule)
appdimens-dynamic-kmp/Kotlin MultiplatformSame vocabulary as appdimens-dynamic, multiplatform targetsWork in progressTest line …appdimens-dynamic:4.0.0 — first KMP stable aimed at 1.0.0
appdimens-flutter/Flutter (Android / iOS / Web / desktop)AppDimens.fixed(_), .dynamic(_), .fluidTo(_), .cm / .mm extensionsWork in progressappdimens: ^2.0.0
appdimens-react-native/React Native (iOS / Android)useAppDimens() hook with balanced / defaultScaling / smart / fluidWork in progressappdimens-react-native@2.0.0
appdimens-web/Web (vanilla / React / Vue / Svelte / Angular)webdimens.balanced(_) + framework-specific hooks/servicesWork in progresswebdimens@2.0.0

GitHub mirrorsdynamic · kmp · sdps · ssps · games · ios · flutter · react-native · web.

Clone with submodules

git clone --recurse-submodules https://github.com/bodenberg/appdimens.git
cd appdimens && git submodule update --init --recursive

Only need one stack? Prefer cloning the upstream repo for that artifact from the author's repositories instead of this umbrella.


Hub vs submodules — who owns what

flowchart LR
  Hub["appdimens hub<br/>(this repo)"]
  Hub --> AndroidGroup["Android"]
  Hub --> Apple["Apple / iOS"]
  Hub --> KMP["Kotlin Multiplatform"]
  Hub --> Flutter
  Hub --> RN["React Native"]
  Hub --> Web
  AndroidGroup --> dyn["appdimens-dynamic Production"]
  AndroidGroup --> sdps["appdimens-sdps Production"]
  AndroidGroup --> ssps["appdimens-ssps Production"]
  AndroidGroup --> games["appdimens-games WIP"]
  Apple --> ios["appdimens-ios WIP"]
  KMP --> kmpArtifact["appdimens-dynamic-kmp WIP"]
  Flutter --> flu["appdimens-flutter WIP"]
  RN --> rn["appdimens-react-native WIP"]
  Web --> webdimens["webdimens WIP"]

Important

Responsibility split

  • Hub (DOCS/ + this README) owns: shared vocabulary, mathematical theory, kernel taxonomy, cross-platform mapping, migration paths, hub-level FAQ. No pinned versions, ever.
  • Submodules own: source, semver, Gradle / npm / pod / pub install lines, R8/ProGuard rules, per-API changelogs, code-level docs, regression tests.

When prose in the hub disagrees with the submodule, the submodule is the source of truth.

Runtime dynamic vs baked sdps / ssps on Android

appdimens-dynamicappdimens-sdps / appdimens-ssps
ComputationRuntime from live ConfigurationPre-computed res/values-sw*/dimens.xml buckets
FlexibilityAll 14 kernels, per-call AR / inverter / qualifier flagsOne curve per artifact, @dimen friendly
CostTiny AAR; ~5 ns cache hit, ~2 ns no-AR multiplyLarger resource tables, zero runtime
XML integrationOnly via Compose / code packageFirst-class @dimen/_16sdp etc.

Many teams mix both: SDP/SSP for XML layouts, appdimens-dynamic for Compose / Kotlin-side dimensions. Full taxonomy of when to pick which: DOCS/THEORY.md and DOCS/GUIDE.md.


Documentation map (DOCS/)

The DOCS/ folder is theory-only — concepts, math, cross-platform mapping, migration. Choose your learning path:

GoalReadThen
I want to ship todayDOCS/GUIDE.md — strategy decision tree, FAQs, common patternsSubmodule README for your stack
I want to understand the mathDOCS/THEORY.md — formal kernels, axioms, comparisonsMATHEMATICS-AND-CALCULUS.md
I'm migrating from 1.x / 2.x / SDP–SSPDOCS/MIGRATION.md — legacy .fxdp / .dydp / unified DSL → Compose 3.x packagesThe submodule changelog you ship
I'm porting across stacksDOCS/PLATFORMS.md — concept ↔ submodule API, verified constantsThe matching submodule README
I rotate / foldable my UIDOCS/ORIENTATION.md — base orientation, *Ph / *Lw / *Lh invertersCOMPOSE-API-CONVENTIONS.md
I want copy-paste recipesDOCS/EXAMPLES.md — long-form snippets per stackThe submodule's app/ sample where available

Visual & interactive resources

Precision scaling PDF Android scaling PDF UI scaling PDF Beyond DP PDF

Scaling comparison HTML Dynamic vs fixed HTML

Image gallery


Performance snapshot

Numbers captured on Xiaomi 2107113SG (Snapdragon 888 · Android 14) physical hardware, debug build without minify. Full methodology, R8 deltas, and per-device variability discussed in appdimens-dynamic/PERFORMANCE.md.

OperationResultNotes
Raw math, no AR~2 nsSCALED / AUTO / FLUID / PERCENT fast-bypass path (cache is intentionally skipped — a 2 ns multiply is cheaper than the ~5 ns hash)
Raw math with AR~45 nsln() evaluation on hardware
Cache hit (no AR)~5 nsLock-free padded sharded cache lookup
Cache hit (with AR)~35 nsZero-math path for AR kernels
Batch resolution (100 items)~169 nsgetBatch() API, SIMD-friendly loop
Persistence load (100 entries)0.76 msCold start from disk-persisted cache
JVM cache hit (local)~1 nsLinux + JVM 17
Real-world (1 000-item Compose scroll)~996 ms total / ~996 µs per itemIndistinguishable from baseline; 0% jank at 120 FPS

With R8 + minify on release builds, the dashboard-style harness drops further (~125–155 ns micro combined, ~367–380 ns per-item macro). See the Build variants & R8 note at the top of PERFORMANCE.md.


Comparison with alternatives

The hub does not publish a single global "score / 100" ranking — comparisons depend heavily on form-factor mix, design philosophy, and what you measure. Instead, here are the honest categorical trade-offs. Quantitative kernel comparisons live in DOCS/THEORY.md §8–10.

ApproachWhat it does wellWhat AppDimens adds
Raw dp / sp / pt / pxZero deps, predictable on the calibrated deviceCalibration across canvas extent and aspect ratio, not just density
Linear SDP / SSP (e.g. Intuit sdp-android)Pre-computed @dimen resources, XML-nativeSame baked resources (appdimens-sdps/-ssps) plus non-linear kernels (auto, logarithmic, power, fluid) — and you can mix runtime computation in Compose
CSS vw / vh / clamp() / container queriesFirst-class in modern browsers, no JSA single vocabulary that travels off the Web (iOS / Android / Flutter / RN) — appdimens-web integrates clamp()-style behaviour as the fluid kernel
ScreenUtil / size-matters / similar librariesSingle dependency, friendly APIStrategy-per-call-site instead of a single global curve; foldable + multi-window heuristics; AR compensation; reproducible math doc per kernel

If you are already happy with one of the above on a phone-only product, AppDimens may be overkill — see GUIDE.md "Fast path / When AppDimens is overkill".


FAQ

Which strategy should I reach for first? auto (BALANCED) for multi-device, scaled for phone-first / SDP-style, percent for axis-heavy containers. Full decision tree: DOCS/GUIDE.md "Fast path".

Will this break my existing SDP / SSP layouts? No. appdimens-sdps / appdimens-ssps ship the canonical SDP/SSP resource tables (@dimen/_16sdp, …) so existing XML keeps working. You can adopt the runtime appdimens-dynamic kernels gradually inside Compose. Migration story: DOCS/MIGRATION.md.

Does it work in pure XML layouts? Yes — appdimens-sdps and appdimens-ssps are XML-native (@dimen/_16sdp, @dimen/_18ssp, …). For runtime kernels, appdimens-dynamic exposes a code package for Views and a compose package for Compose.

Does it work inside @Preview / unit tests? Yes. Every kernel is a pure function of (base, Configuration). Compose previews resolve as on a regular device — and you can override LocalConfiguration to simulate any canvas.

Will rotation / foldables break my proportions? By design no. Effective-axis selection consults Configuration and WindowManager fold state. For authored portrait → device landscape (or vice versa), use the *Ph / *Lw / *Lh inverter tokens. See DOCS/ORIENTATION.md.

Is the cache thread-safe? Yes. It is a lock-free padded sharded cache (128-byte shards to avoid false sharing on ARM64) with bypass for the simplest no-AR multiplies. Details in appdimens-dynamic/PERFORMANCE.md.

Can I keep some sizes truly constant? Yes — use raw Dp / Sp (or .dp / .sp Compose extensions) for icons that must stay 24 dp everywhere. The conceptual NONE kernel is exactly this.

What changed since 2.x? On Compose, the old unified DSL (.fxdp, .dydp, .balanced().dp) was split into strategy packages (compose.scaled, compose.auto, compose.percent, …). Naming rename Fixed → DEFAULT, Dynamic → PERCENTAGE is purely narrative; Gradle uses scaled and percent. iOS / Flutter / RN / Web keep their builder names. Full mapping: DOCS/MIGRATION.md.


Roadmap & status

  • Production: appdimens-dynamic, appdimens-sdps, appdimens-ssps (Android).
  • 🔄 Work in progress: appdimens-ios, appdimens-dynamic-kmp (first stable aimed at 1.0.0), appdimens-flutter, appdimens-react-native, appdimens-web, appdimens-games.
  • 🧪 Hub theory: kernel taxonomy and verified constants are stable; benchmark deltas continue to track new device classes (PERFORMANCE.md).

Issues about this hub repo (typos, dead links, missing concept docs) → Hub issues. Shipping bugs (compile errors, wrong numbers, build problems) belong in the submodule repository you depend on so they reach the maintainers and CI of that artifact.


Contributing, security, license

Contributing Security Code of Conduct Changelog License

  • CONTRIBUTING.md — how to propose hub or submodule changes, doc style, PR checklist.
  • SECURITY.md — responsible disclosure channel for vulnerabilities.
  • CODE_OF_CONDUCT.md — community expectations.
  • CHANGELOG.md — high-level coordinated-release history; each submodule maintains its own detailed changelog.
  • LICENSE — Apache 2.0.

Author

Jean Bodenberg@bodenberg · appdimens-project.web.app

If AppDimens helps your project, please ⭐ this repo and the submodules you use — visibility is what funds further work.


📚 DOCS · 📘 GUIDE · 📐 THEORY · 💡 EXAMPLES · 🧭 PLATFORMS · ♻️ MIGRATION · 🔄 ORIENTATION