L-Shaped Stair with Landing Calculator

Overall dimensions
Landing
Steps
Stringers
Timber stock

This stair clears every point along it — minimum headroom is 2150 mm, at step 6 of the lower flight, above the 2000 mm required.

Diagram
Riser height175mm
Tread depth305mm
Minimum headroom clearance2.15m
Dimensions
MRiser height175 mm
NGoing280 mm
OPitch angle32.0°
TTread depth305 mm
PLower flight run1.68 m
QUpper flight run3.36 m
VLanding height (above base floor)1.23 m
WUpper flight rise2.28 m
RLower flight stringer length2,079 mm
SUpper flight stringer length4,058 mm
Risers, lower flight7
Risers, upper flight13
Headroom
Minimum headroom clearance2.15 m
Occurs at step6
Opening would need to start at (from landing)-25 mm
Opening would need to be at least3.39 m
Materials
Stringer timber required (all 4)12.27 m
Total tread area4.94 m²
Tread timber volume158.11 L
Stringer timber volume133.39 L
Tread timber, linear length16.2 m
Tread boards to buy4
Riser timber, linear length16.2 m
Riser boards to buy4
Stringer timber, linear length12.27 m
Stringer boards to buy3
Parts list
TreadCount: 18
Length
900 mm
Width
305 mm
Thickness
32 mm
RiserCount: 18
Length
900 mm
Width
143 mm
Thickness
19 mm
Stringer, lower flightCount: 2
Length
2,079 mm
Width
286 mm
Thickness
38 mm
Stringer, upper flightCount: 2
Length
4,058 mm
Width
286 mm
Thickness
38 mm

About this calculator

This calculator helps design an L-shaped (90° turn) stair with a landing — two flights joined by a horizontal landing — from an existing floor opening. Enter the opening's dimensions, the total rise, a preferred riser height, and a landing-height target, and it works out each flight's riser height and tread size, checks headroom along the whole climbed path (both flights and the landing, not just the upper flight), the landing's width, and produces a drawing plus a timber cutting list. Like the straight-stair calculator, this is a design (kind: 'design') calculator, not a quantity one — the result is the drawing itself.

Formula

The opening is the primary given, not a result — the same principle as the straight-stair calculator:

total riser count = round(total rise / preferred riser height)   (clamped to 4-40)
riser height = total rise / riser count   (one division for the whole stair, exactly)

lower flight riser count = round(landing height target / riser height)
upper flight riser count = total riser count - lower flight riser count

The landing height target (landingHeight) replaces the old direct lower-flight riser count field — it is a preferred value (e.g. a landing at a window or a mid-level door) that this rounds to, not an exact promise: the real landing position (reference V) is lower flight riser count × riser height, which may differ slightly from the target.

Going is applied UNIFORMLY to both flights, and its source depends on openingExactFit:

if openingExactFit = false (DEFAULT since 2026-08-23):
  going = your own `going` input
  upper flight run = going × upper flight tread count

if openingExactFit = true (opt-in):
  upper flight run = opening length - nosing overhang
  going = upper flight run / upper flight tread count

lower flight run = going × lower flight tread count   (the same going, from above)

The lower flight has no opening of its own, so its own run simply inherits the same going, to keep both flights' treads the same size (as a real flight should be).

Why the default changed: in real practice a floor opening is normally cut LARGER than the upper flight and the flight fixed against one edge of it, leaving the rest of the hole open past the flight's own base (often over the landing) — an opening that exactly matches the upper 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 either flight. openingExactFit = true remains available for the case where the opening genuinely was cut to the upper flight's own size — then the opening genuinely sets the going and the upper flight's run, as described below.

Why the nosing overhang (noseOverhang) 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 of the upper flight, whose nosing projects past the flight's own starting point itself. If the upper flight's 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. That was a modelling bug, not physics: a real floor opening has to span the first tread's own nosing too, not just the flight's "structural" run. Subtracting the nosing overhang from the upper flight's run puts the opening's near edge exactly nosing overhang before the flight's own starting point — exactly enough for the first tread's own nosing to fall inside it.

pitch angle = atan2(riser height, going)
each flight's stringer length = √(that flight's rise² + that flight's run²)

Headroom is now checked along the WHOLE climbed path — every tread of the lower flight, the landing itself, and every tread of the upper flight, not just the upper flight. A person climbs from the base floor: up the lower flight, across the landing, up the upper flight; the ceiling (the underside of the upper floor slab) is one flat plane across the whole building, not just above the upper flight — the opening only removes it where it actually cuts through. Each point's height (a tread's nosing, or the landing) is compared against this one shared ceiling line, measured from the base floor; a point is exempt from the check only if its whole floor-plan footprint falls inside the opening — partial overlap does not exempt it. This fixes a real bug in the previous version of this calculator: only the upper flight was checked, locally to the landing, so a landing sitting well under a still-solid part of the same flat slab (common back then, since the opening was always cut exactly to the upper flight's own size) was reported as fine regardless of how low its true clearance actually was. A generously-sized opening can genuinely protect the landing too today (see Assumptions and limits below) — exactly why this whole-path check, not an upper-flight-only one, is what has to run.

requiredOpeningStart/requiredOpeningLength remain concepts scoped to the upper flight alone — they answer "what opening size would this flight alone need", independent of the whole-path check above. So they may show the opening you have is sufficient for the upper flight while the overall, whole-path check still reports a problem elsewhere — at the landing or the lower flight, where these two values don't apply at all. requiredOpeningStart can also be NEGATIVE — that is a real answer, not an invalid one: it means the opening would need to start somewhat BEFORE the flight's own starting point (to give the first tread's own nosing the headroom it needs), not that the requirement is already met right from the flight's own base.

The landing width check (the landing's dimension perpendicular to the direction of travel must be at least the flight width) and the step/pitch comfort checks are unchanged from before — see below, Assumptions and limits.

Worked example

Defaults: opening length 4310 mm, opening width 1100 mm, stair centered in the opening, total rise 3500 mm, stair width 900 mm, floor structure thickness 300 mm, required headroom 2000 mm, top tread flush with the floor, landing square at stair width, landing height target 1225 mm, preferred riser height 175 mm, going 280 mm (a real input, openingExactFit = false), tread thickness 32 mm, nosing overhang 25 mm, riser board thickness 19 mm, stringer thickness 38 mm, stringer depth 286 mm, standard board length 4800 mm.

total riser count = round(3500 / 175) = 20   (divides evenly)
riser height = 3500 / 20 = 175 mm   (exactly)

lower flight riser count = round(1225 / 175) = 7   (exactly)
upper flight riser count = 20 - 7 = 13

upper flight tread count = 13 - 1 = 12 (top tread flush with the floor)
going = 280 mm   (a real input, opening length plays no part)
upper flight run = 280 × 12 = 3360 mm

lower flight tread count = 7 - 1 = 6 (the landing itself is the last "tread")
lower flight run = 6 × 280 = 1680 mm

tread depth = 280 + 25 = 305 mm
pitch angle = atan2(175, 280) ≈ 0.5586 rad ≈ 32.01°

landing height (actual) = 7 × 175 = 1225 mm   (exactly matches the target)
upper flight rise = 3500 - 1225 = 2275 mm

lower stringer length = √(1225² + 1680²) ≈ 2079.19 mm
upper stringer length = √(2275² + 3360²) ≈ 4057.74 mm

For these inputs the calculator returns exactly this: riser height 175 mm, going 280 mm, tread depth 305 mm, landing height 1225 mm, lower stringer length ≈2079.19 mm, upper stringer length ≈4057.74 mm, 7 risers in the lower flight and 13 in the upper.

Headroom: for these defaults the calculator passes cleanly with no warnings or errors at all — the smallest clearance (2150 mm, a 150 mm margin over the required 2000 mm) is found on the LOWER FLIGHT's 6th tread (the one closest to the landing), not the landing itself or the upper flight: the opening (4310 mm) was deliberately cut larger than the upper flight's run (3360 mm) plus the landing's own width (900 mm), so it fully covers BOTH the whole upper flight AND the landing — both are exempt. That exposes a different, real constraint instead: the lower flight's own topmost tread (one riser below the landing) sits on the perpendicular axis from the opening's own width and stays under solid, uncut slab — no reasonably-sized opening reaches it (see Assumptions and limits). 2×riser+going = 2×175+280 = 630 mm — exactly DIN 18065's own target, dead centre of the 600-660 mm comfort band.

The separate, upper-flight-only "what opening size would this need" answer returns a start of -25 mm (negative — the opening would need to start 25 mm before the flight's own starting point for the first tread's nosing to get the headroom it needs) and a length of ≈3385 mm — it evaluates only the upper flight's own need, in isolation from the whole-path check above, and comes out well short of the actual 4310 mm opening, since that opening was deliberately cut to cover the landing too, not just the upper flight.

Timber list: 18 treads (6 in the lower flight + 12 in the upper) × 900 mm wide × 305 mm deep tread boards — 4 boards of 4800 mm (16,200 mm total length / 4800 mm ≈ 3.375, rounded up). 18 riser boards (out of 20 risers total — 2 risers, which top the landing/floor rather than a tread, are skipped because their board height is smaller than the floor structure thickness): also 4 boards. 4 stringers (2 lower at ≈2079.19 mm, 2 upper at ≈4057.74 mm, ≈12,273.85 mm in total): 3 boards.

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 a preferred riser height (targetRiserHeight) for the whole stair and a landing-height target (landingHeight) are entered instead, and the real riser count on each flight is computed from them.

Why does the same going apply to both flights, even though only the upper flight has an opening? Because going is one, shared value (by default a real input; with openingExactFit = true, derived from the one flight connected to the floor opening, the upper flight) — the lower flight's run simply inherits the same going, so both flights end up with the same-sized treads, as a real flight should.

Does the headroom check cover only the upper flight? No, not any more. The check now covers the whole climbed path — the lower flight, the landing, and the upper flight — comparing each point's height against one shared ceiling line, measured from the base floor. The opening only exempts points whose whole floor-plan footprint falls inside it.

What sets the landing size? By default the landing is square, equal to the stair width — the only size that keeps both flights the same width through the turn, with no unused floor at the corner. A larger landing can be chosen by entering its own side length manually.

Why does the calculator cite an IRC (US) standard for a Lithuanian-market calculator? Because the exact landing-width requirement (landing not narrower than the flight) matches IRC R311.7.6's wording precisely, while Lithuanian STR 2.02.01:2004 does not state this general ratio as its own rule — it only gives absolute minimums for specific stair categories, not a general "landing ≥ flight" rule.

Does turnDirection change any computed number? No. It is purely a drawing parameter — it decides which way the upper flight's plan extends from the landing, but affects no computed result (riser height, going, pitch, stringer length, timber quantities). Both turnDirection and stairPositionInOpening are expressed from the climber's own left/right hand, standing at the base of the flight before the first step — not the drawing's own +X axis (model +X is the climber's LEFT hand).

Assumptions and limits

meta.standards cites DIN 18065, STR 2.02.01:2004 (both for the 2×riser+going comfort check, with the same 630/650 mm disagreement as the straight-stair calculator), and IRC R311.7.6 (for the landing width check). The 30-45° pitch comfort band remains an uncited general rule.

The preferred riser height (targetRiserHeight) is bounded to 150-200 mm, the same bound as the straight-stair calculator. The landing height target (landingHeight) has no cited basis of its own — it is a freely chosen design decision (e.g. a landing at a window), which the real riser count only rounds to.

The required headroom is a user input with no cited minimum — it is set by national or local requirements that differ from each other.

Headroom is checked along the whole climbed path (both flights and the landing), compared against one flat ceiling line across the whole building — a more accurate model than before (see Formula), but still an assumption: the real underside of the floor structure may not be perfectly flat (beams, services). requiredOpeningStart/requiredOpeningLength answer only "what opening size would suffice for the upper flight" — they do NOT reflect the whole-path check's own result, and may show that the opening you have is sufficient even when the overall check returns an error for the landing or lower flight.

The defaults (opening length, total rise, landing height target) were chosen so the default stair clears its own headroom check with real margin (see Worked example), not merely on a technicality — an earlier version of this calculator shipped with defaults that opened on an error. This doesn't weaken the check itself: any combination where the landing sits high enough relative to the total rise can still fail it — that remains a real, not an artificial, constraint.

Until 2026-08-23, this section stated that the opening never exempts the landing itself, since the opening only ever covers the upper flight's own footprint. That was only ever true for the OLD default (openingExactFit = true, where the opening was deliberately cut to exactly the upper flight's own size, leaving nothing left over). With the new default (openingExactFit = false), a generously-sized opening genuinely CAN exempt the landing too — verified directly, not just in theory: the reported diagnostic switches from headroom-ok-landing to headroom-ok-lower-flight, i.e. the landing really does stop being the worst point. But covering the landing exposes a DIFFERENT, previously-hidden constraint: the LOWER flight's own topmost tread (one riser below the landing) stays under solid, uncut slab no matter how the opening is sized, because the lower flight sits on the axis PERPENDICULAR to the opening's own width — reaching it would require widening the opening enough to swallow the lower flight's entire run too, an unrealistically wide hole, not one "cut a bit larger than the flight". The new, real ceiling is landing height ≤ total rise - floor structure thickness - required headroom + riser height — one riser height more forgiving than before, not a jump to a genuine midpoint: swept 2700-3300 mm total rise at 30-50% landing height and confirmed every combination above roughly 33-35% fails on the LOWER flight now, not the landing. A true 50% midpoint position remains out of reach even with this fix, at any believable house rise. This calculator's defaults (total rise 3500 mm, landing height 1225 mm — 35% of the total rise, seven risers) reach the highest landing position, in clean riser-count terms, that a still-believable house rise allows — five percentage points higher than the previous (30%) version, but still not a genuine midpoint.

One floor-structure-thickness input serves two purposes: the upper floor structure's own thickness (the ceiling height beneath it) and the landing's own construction thickness — a deliberate simplification, assuming the landing is built the same way as the floor it sits under.

This calculator is one of two on this platform that return parts[] — real physical pieces (treads, risers, both flights' stringers) with actual cutting dimensions. The timber board count is a simple quantity division by the standard board length, not an optimized cutting plan — the same logic as the straight-stair calculator.

kalkivo