About this calculator
This calculator helps design a straight flight of stairs from an existing floor
opening: enter the opening's dimensions, the total rise (floor to floor), and your
preferred riser height, and it works out the riser count, each step's dimensions, checks
headroom along the whole climbed path, and produces a drawing plus a timber cutting list.
The result is the drawing itself, not a single number: this is a design (kind: 'design')
calculator, not a quantity one.
Formula
The opening is the primary given, not a result — it is measured against an existing (or planned) hole in the floor, not a stair someone has already designed. Everything else is derived from it and the total rise:
riser count = round(total rise / preferred riser height) (clamped to 2-20)
riser height = total rise / riser count (exactly, with no lost remainder)
tread count = riser count - 1, if the top tread sits flush with the floor
= riser count, if every riser gets its own tread
The riser count is no longer a direct input field — that used to require the user to
already know the answer. Now only a preferred riser height (targetRiserHeight) is
entered, and the real riser count and exact height are derived from it and the total rise.
Going (tread depth minus nosing) — two paths:
if openingExactFit = false (DEFAULT since 2026-08-23):
going = your own `going` input
total run = going × tread count (independent of the opening length)
if openingExactFit = true (opt-in):
total run = opening length - nosing overhang
going = total run / tread count
Why the default changed: in real practice a floor opening is normally cut LARGER than
the flight and the flight fixed against one edge of it, leaving the rest of the hole open
past the flight's own base (usually over the landing, or the room below) — an opening that
exactly matches the flight's own length is the rarer case, not the general one. So
openingExactFit = false (the new default) treats going as a real, independent design
input — the opening length plays no part in sizing the flight at all. openingExactFit = true remains available for the case where the opening genuinely was cut to the flight's own
size — then the opening genuinely determines the going and the whole run, as described
below.
Why the nosing overhang is subtracted (openingExactFit = true path only): every tread's
own nosing projects forward past its own riser line by exactly noseOverhang — including the
FIRST tread, whose nosing projects past the flight's own starting point itself. If the total
run were set to exactly the opening's own length (no subtraction), the opening's near edge
would always coincide with the flight's own starting point, and the first tread's nosing
would always sit just outside the opening's own boundary — no matter how the opening was
sized or positioned. Subtracting the nosing overhang from the total run puts the opening's
near edge exactly nosing overhang before the flight's own starting point (see below) —
exactly enough for the first tread's own nosing to fall inside it.
pitch angle = atan2(total rise, total run)
stringer length = √(total rise² + total run²)
The flight's position under the opening: the flight's top structurally always lands at
the opening's far edge (that is where the upper floor's surface begins). The opening's near
edge (reference A) is a derived value, not an input: total run − opening length. Under
openingExactFit = false (the default), this is typically well negative — a real opening is
normally cut larger than the flight, so going (a real input, not derived from the opening)
usually produces a run shorter than the opening, meaning the flight's own base already sits
inside the opening's own footprint. Under openingExactFit = true (opt-in), this value is
always exactly minus the nosing overhang (e.g. -25 mm with the default 25 mm overhang) —
not zero — because the run is then, by construction, the opening length minus the nosing
overhang (see above). There is no longer a separate "opening start" field — its old
definition ("from the flight's own base") no longer makes sense once the flight's own base is
itself a derived, moving position.
The flight's position across the opening's width is set by stairPositionInOpening
(left/centered/right) — the one remaining free position choice. The reference point
is the climber themselves, standing at the base of the flight facing it, before taking the
first step: 'right' always means the climber's own right hand, not the drawing's own +X
axis (model +X is the climber's LEFT hand). This convention is shared by every stair
calculator on this platform (see CLAUDE.md).
Headroom is checked along the whole climbed path under the ceiling — every tread that falls before the opening's own near edge, measured as the vertical distance from its nosing to the ceiling (total rise minus floor structure thickness), assuming the ceiling runs uncut across that whole span. If the smallest such clearance is below the required headroom, an error is returned along with how far the opening would need to extend. The calculator also reports the minimum opening length (and its own start point) that would be needed for headroom alone — independent of the opening you actually entered.
The step-comfort check (2×riser+going) and the pitch-comfort check (30-45°) are unchanged from before — see below, Assumptions and limits.
Worked example
Defaults: opening length 4700 mm, opening width 1100 mm, stair centered in the opening,
total rise 2900 mm, stair width 900 mm, preferred riser height 175 mm, going 280 mm (a real
input, openingExactFit = false), top tread flush with the floor, tread thickness 32 mm,
nosing overhang 25 mm, riser board thickness 19 mm, stringer thickness 38 mm, stringer depth
286 mm, floor structure thickness 300 mm, required headroom 2000 mm, standard board length
6000 mm.
riser count = round(2900 / 175) = round(16.571) = 17
riser height = 2900 / 17 ≈ 170.59 mm
tread count = 17 - 1 = 16 (top tread flush with the floor)
going = 280 mm (a real input, opening length plays no part)
total run = 280 × 16 = 4480 mm
tread depth (incl. nosing) = 280 + 25 = 305 mm
opening's near edge = 4480 - 4700 = -220 mm
pitch angle = atan2(2900, 4480) ≈ 0.5745 rad ≈ 32.92°
stringer length = √(2900² + 4480²) ≈ 5336.70 mm
2×riser+going = 2×170.59 + 280 ≈ 621 mm (inside the 600-660 mm band -> no warning)
ceiling height under the floor = 2900 - 300 = 2600 mm
The opening's near edge (-220 mm) sits just before the flight's own starting point — the opening (4700 mm) was deliberately cut larger than the flight (4480 mm), as is normal in real practice (see Formula), so ALL 16 treads fall inside the opening. The calculator returns an informational note that no tread sits under a still-solid part of the floor. The separate, headroom-only "what opening size would this need" answer in this case returns a start point of ≈815 mm and a length of ≈3665 mm — an isolated figure, independent of the opening actually in use, showing that a considerably more modest opening (from ≈815 mm up to the flight's own top) would also satisfy headroom alone.
For these inputs the calculator returns exactly this: riser height ≈170.59 mm, going 280 mm, tread depth 305 mm, total run 4480 mm, stringer length ≈5336.70 mm, 17 risers, 16 treads. Diagnostics: a single informational note that no tread sits under a still-solid part of the floor — no warnings (2×riser+going = 621 mm falls inside the 600-660 mm band).
Timber list for these inputs: 16 tread boards (900×305×32 mm each — needing 3 boards of 6000 mm, total length 14,400 mm), 17 riser boards (900×≈138.59×19 mm each, needing 3 boards of 6000 mm — total length 15,300 mm), 2 stringers (each ≈5336.70×286×38 mm, total length ≈10,673.41 mm, needing 2 boards of 6000 mm).
FAQ
Why isn't the riser count among the inputs any more?
Because that used to require the user to already know the answer. Now only a preferred
riser height (targetRiserHeight) is entered — the real riser count and exact height are
computed from it and the total rise.
Does the opening only get checked, or does it genuinely set the going?
That depends on openingExactFit. By default (false), the going comes from your own
going field, and the run is computed from it — the opening length plays no part in sizing
it, since a real opening is normally cut larger than the flight it serves. Switching
openingExactFit on makes the opening genuinely set both the going and the whole run
instead — the total run then always ends up equal to the opening length minus the nosing
overhang (see Formula — not exactly the opening length, so the first tread's own nosing falls
inside the opening) — useful when the opening genuinely was cut to the flight's own size. The
comfort check still runs and warns if the result falls outside the 2×riser+going band either
way.
Why isn't there a separate "opening start" field any more? Because it used to be defined relative to the flight's own base, and the flight's base is now a derived, moving position, not a fixed second reference point. The opening's near-edge position is now shown as a result (on the drawing, labelled A), not entered.
What do 'left'/'right' mean for the flight's position in the opening?
The climber's own right/left hand, standing at the base of the flight facing it — not a
drawing axis. The same convention is used across every stair calculator on this platform.
Is headroom checked at just one point? No — every tread that falls before the opening's own near edge is checked, and the smallest of those clearances is reported. The calculator also reports the minimum opening length that would be needed for headroom alone — an answer to "how much would be enough", independent of the opening you actually entered.
Why does the calculator mention two different standards for the 2×riser+going check? Because DIN 18065 and Lithuanian STR 2.02.01:2004 both define the same formula, but with different targets (630 mm and 650 mm respectively) — a real disagreement between the two standards, which the calculator reports honestly rather than silently picking one as "correct".
Does the timber list account for cutting waste? No. Each member type's total required length is simply divided by the standard board length and rounded up — that is a quantity estimate, not an optimized cutting plan.
Assumptions and limits
meta.standards cites DIN 18065 and STR 2.02.01:2004 — both used for the same 2×riser+going
comfort formula, but with different targets (630 mm and 650 mm) — this disagreement is
reported, not resolved, by the calculator. The 30-45° pitch comfort band is a general rule
matching neither of these two standards exactly, and no standard is cited for that check.
The required headroom is a user input with no cited minimum — it is set by national or local requirements that differ from each other, so the calculator does not state which one applies.
The preferred riser height (targetRiserHeight) is bounded to 150-200 mm — the upper
bound matches STR 2.02.09:2005 §47.4's interior riser-height ceiling (≤200 mm); the lower
bound is this calculator's own judgment call (a shallower target only ever lengthens the
run), not a cited source. The exact-fit-to-opening path's own internal clamp (220-400 mm) is
only a sanity range for that path itself — the going field's own bounds (150-500 mm,
applied in the default openingExactFit = false path) are deliberately wider, since a real
design choice routinely needs to go outside the comfortable range when floor space demands
it; a separate diagnostic, not these bounds, reports whether the result is comfortable.
This calculator is one of two on this platform that return parts[] — real physical pieces
(treads, risers, stringers) with actual cutting dimensions, not just a total material
quantity. The timber board count is a simple quantity division by the standard board length,
not an optimized cutting plan.
The stringer's remaining depth below the notch (shown on the detail drawing) has no cited minimum — the required remaining depth depends on span tables that vary by jurisdiction.