A zero-build, browser-native utility for calculating visually correct nested corner radii from outer radius, padding, and inner radius inputs.
Live Demo: Open the calculator in your browser
Important
This repository is a static UI utility, not a packaged runtime library. The documentation below reflects the actual codebase structure and behavior present in this repository.
- Title and Description
- Features
- Tech Stack & Architecture
- Getting Started
- Testing
- Deployment
- Usage
- Configuration
- License
- Contacts & Community Support
- Real-time nested border-radius calculation using the relationship
inner + padding = outer. - Bidirectional synchronization across all three parameters:
- editing
outer radiusrecalculatesinner radius - editing
paddingrecalculatesinner radius - editing
inner radiusrecalculatesouter radius
- editing
- Immediate visual preview of concentric rounded rectangles to validate geometry before shipping CSS.
- Dual input modalities for each dimension:
- numeric text input for precise values
- range sliders for fast exploratory tuning
- Built-in guardrail logic that clamps computed values to non-negative results.
- Zero-build architecture with no bundler, package manager, or runtime dependency installation required.
- Multilingual interface support driven by a modular ISO locale registry with per-language files.
- Responsive, single-page layout suitable for desktop and tablet browser workflows.
- GitHub Pages-friendly hosting model for frictionless publishing and sharing.
Note
The calculator operates on pixel values in the UI, but the underlying radius relationship is generic and can be adapted to other unit systems if you modify the client-side script.
HTML5for the application shell, semantic structure, and control wiring.CSS3for layout, component styling, responsive behavior, and preview visualization.Vanilla JavaScript (ES6+)for state synchronization, rendering, and localization updates.Google Fonts(Inter) for typography.GitHub Pagesas the natural deployment target for the static site.
Nested-Radius-Calculator/
βββ .github/
β βββ FUNDING.yml # Funding links used by GitHub
βββ LICENSE # Apache 2.0 license text
βββ README.md # Project documentation
βββ img_nested-radius-calculator.PNG
β # README preview asset
βββ index.html # Single-page app markup and control layout
βββ process_pr.py # Repository utility script
βββ script.js # Radius calculation, event handlers, and rendering logic
βββ style.css # Theme, spacing, responsive layout, and preview styling
βββ i18n/ # Locale registry, validation, and per-language dictionaries
βββ index.mjs # i18n entry point and key synchronization guard
βββ locales/ # One ISO-locale file per supported language
The project intentionally avoids a build pipeline. That decision keeps onboarding trivial, reduces maintenance overhead, and makes the tool easy to host on any static file server.
Rather than introducing a framework or external state container, the implementation reads directly from DOM inputs and writes back to the DOM after each interaction. For a small, deterministic calculator, this keeps the execution model obvious and easy to debug.
The core interaction model is built around a simple invariant:
innerRadius = max(outerRadius - padding, 0)
outerRadius = innerRadius + padding
This ensures the preview remains logically coherent regardless of which control the user edits.
Translations are stored in dedicated locale modules under i18n/locales/ and applied to nodes marked with data-i18n. A central registry validates that every locale exposes the exact same keys before the UI initializes, preventing missing-string runtime errors while keeping the system lightweight and framework-agnostic.
The rendered nested boxes visually confirm the numerical calculation. This is especially useful for UI engineers and designers validating perceptual corner balance rather than relying on raw numbers alone.
flowchart LR
A[User edits input or slider] --> B[JavaScript event listener]
B --> C{Source field}
C -->|Outer changed| D[Recompute inner = max outer - padding]
C -->|Padding changed| E[Recompute inner = max outer - padding]
C -->|Inner changed| F[Recompute outer = inner + padding]
D --> G[Sync paired input and range controls]
E --> G
F --> G
G --> H[Render preview styles]
H --> I[Updated border-radius and padding visualization]
Tip
If you plan to extend the project, keep the current formula logic isolated in script.js so alternate unit systems, presets, or export formats can be added without changing the core HTML structure.
You only need a modern browser to use the calculator locally.
Recommended tooling:
Google Chrome,Mozilla Firefox,Safari, orMicrosoft EdgeGitfor cloning the repositoryPython 3or any simple HTTP server if you prefer serving the files instead of openingindex.htmldirectly
Note
The project does not require npm, pnpm, yarn, Docker, or a JavaScript bundler.
Clone the repository and run it locally using one of the following approaches.
git clone https://github.com/OstinUA/Nested-Radius-Calculator.git
cd Nested-Radius-CalculatorOpen index.html in your browser:
# Linux
xdg-open index.html
# macOS
open index.html
# Windows PowerShell
start index.htmlgit clone https://github.com/OstinUA/Nested-Radius-Calculator.git
cd Nested-Radius-Calculator
python3 -m http.server 8080Then visit:
http://localhost:8080
Important
Serving the site over HTTP is the safest option if you later add assets, API mocks, or browser features that behave differently under file:// URLs.
This repository currently does not include an automated test suite, linter configuration, or CI-driven browser tests. Validation is therefore manual unless you add tooling.
Run a local server:
python3 -m http.server 8080Then verify the following behaviors in the browser:
- Changing
Outer RadiusupdatesInner Radiusasmax(outer - padding, 0). - Changing
PaddingupdatesInner Radiuswith the same non-negative clamp. - Changing
Inner RadiusupdatesOuter Radiusasinner + padding. - Range sliders and number inputs remain synchronized for all three values.
- The preview boxes update instantly to reflect new radius and padding values.
- Switching languages updates all
data-i18nlabels, the document title, and footer text across every supported locale. - Responsive layout remains usable below
768pxviewport width.
If you choose to introduce automated checks, these are sensible starting points for a static frontend project:
# HTML validation example
npx html-validate index.html
# CSS linting example
npx stylelint "*.css"
# JavaScript linting example
npx eslint script.js i18n/index.mjs i18n/locales/*.mjsWarning
The commands above are recommendations only. They are not wired into the repository today and will fail until the corresponding toolchain is added.
The project is well suited for static hosting platforms.
Because the application consists entirely of static assets, GitHub Pages is the most natural deployment path.
- Push the repository to GitHub.
- Ensure the default branch contains
index.htmlat the publish root. - Enable Settings β Pages in the GitHub repository.
- Select the branch and folder to publish.
- Confirm the generated site URL.
You can also deploy the repository to any static platform, including:
- GitHub Pages
- Netlify
- Vercel static hosting
- Cloudflare Pages
- Amazon S3 + CloudFront
- Internal Nginx or Apache static hosting
- Keep
index.html,style.css,script.js, and thei18n/directory in their current relative paths. - Verify that the Google Fonts stylesheet is reachable in your deployment environment.
- Confirm the preview image path if you mirror the README externally.
- Set appropriate caching rules for static assets if hosting behind a CDN.
- Optionally version the site with tagged releases for reproducible documentation links.
The repository does not currently ship with a Dockerfile or docker-compose.yml. If containerization is required, a minimal Nginx-based image is sufficient because no server-side runtime is needed.
FROM nginx:alpine
COPY . /usr/share/nginx/htmlCaution
If you containerize the project, exclude .git and non-runtime helper files where appropriate to keep the image small and avoid leaking repository metadata.
The calculator is designed for designers and frontend engineers who need consistent nested corners in cards, panels, dialogs, or inset surfaces.
- Set the parent container radius in
Outer Radius. - Set the space between parent and child in
Padding. - Read the computed
Inner Radius. - Copy the resulting values into your CSS.
If your outer container has a 40px radius and 10px padding:
innerRadius = max(40 - 10, 0) = 30
That maps to CSS like this:
.card {
border-radius: 40px;
padding: 10px;
}
.card__inner {
border-radius: 30px;
}<!-- Minimal HTML shell -->
<link rel="stylesheet" href="style.css">
<script src="translations.js"></script>
<script src="script.js"></script>// The application bootstraps itself on DOMContentLoaded.
// It initializes the default language and seeds the first calculation.
document.addEventListener('DOMContentLoaded', () => {
setLanguage('en');
updateFromOuter(40);
});Outer Radius: 24px
Padding: 8px
Inner Radius: 16px
This is useful for:
- cards with inset content wrappers
- modal shells with padded inner panels
- dashboard widgets with nested surfaces
- design system tokens for rounded containers
Tip
When translating design tokens from Figma or another design tool, start from the outer radius and padding first. That generally produces the most stable inner value for implementation.
This project is intentionally low-configuration.
There is currently no .env file and no runtime environment variable contract.
There are currently no CLI flags or boot-time parameters.
Use this file to customize or extend the available languages.
Current language keys:
enruuahiesarfrptdeid
Translation shape:
const translations = {
en: {
title: "Corner Radius Calculator",
label_outer: "Outer Radius",
label_padding: "Padding",
label_inner: "Inner Radius",
pill_outer: "Outer",
pill_padding: "Padding",
pill_inner: "Inner",
footer: "Open Source project on GitHub | Made for designers"
}
};Use this file to change calculation rules, default values, event behavior, or rendering logic.
Current operational rules:
When outer changes: inner = max(outer - padding, 0)
When padding changes: inner = max(outer - padding, 0)
When inner changes: outer = inner + padding
Use this file to configure theme tokens, spacing, layout breakpoints, and preview appearance.
Example tunables include:
- CSS custom properties in
:root - component spacing and sizing
- responsive breakpoint behavior
- preview colors and border treatments
Use this file to modify form layout, copy, available controls, or initial slider bounds.
Note
Input ranges are currently hard-coded in the HTML:
Outer Radius:0to200Padding:0to100Inner Radius:0to200
If you need larger values, update both the numeric expectations in script.js and the corresponding <input type="range"> attributes in index.html.
This project is licensed under the Apache-2.0 license. See LICENSE for the complete terms and redistribution conditions.
If you find this tool useful, consider leaving a star on GitHub or supporting the author directly.