diff --git a/TUI.Test/ContainerNoRoomMeasureTests.cs b/TUI.Test/ContainerNoRoomMeasureTests.cs
new file mode 100644
index 0000000..a1be514
--- /dev/null
+++ b/TUI.Test/ContainerNoRoomMeasureTests.cs
@@ -0,0 +1,69 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+
+namespace ktsu.TUI.Test;
+
+using ktsu.TUI.Core.Elements.Layouts;
+using ktsu.TUI.Core.Elements.Primitives;
+using ktsu.TUI.Core.Models;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+///
+/// Tests for a container measured at a width its padding takes entirely (ktsu-dev/TUI#249).
+///
+///
+/// The container measured its children at width 0, which reads as "no
+/// constraint", so a word-wrapped child reported its full unwrapped height for text that could
+/// never be drawn, and the rows it claimed were taken from the siblings below.
+///
+[TestClass]
+public sealed class ContainerNoRoomMeasureTests
+{
+ ///
+ /// A border measured at width 1 or 2 reports the bare border, whatever its child is.
+ ///
+ /// A width no wider than the border's padding.
+ [TestMethod]
+ [DataRow(1)]
+ [DataRow(2)]
+ public void BorderWithNoRoomForItsChildMeasuresAsTheBareBorder(int availableWidth)
+ {
+ BorderElement border = new() { Child = new TextElement("one\ntwo\nthree\nfour\nfive") { WordWrap = true } };
+
+ Assert.AreEqual(new Dimensions(2, 2), border.CalculateRequiredDimensions(availableWidth));
+ }
+
+ ///
+ /// A border given one more column than its padding still measures its child.
+ ///
+ [TestMethod]
+ public void BorderWithOneColumnOfRoomStillMeasuresItsChild()
+ {
+ BorderElement border = new() { Child = new TextElement("ab") { WordWrap = true } };
+
+ Assert.AreEqual(new Dimensions(3, 4), border.CalculateRequiredDimensions(3));
+ }
+
+ ///
+ /// The issue's layout: a border squeezed to its padding width beside a label leaves the row
+ /// below where the bare border ends, not where its unwrapped child would.
+ ///
+ [TestMethod]
+ public void SqueezedBorderDoesNotPushTheNextRowDown()
+ {
+ BorderElement border = new() { Child = new TextElement("one\ntwo\nthree\nfour\nfive") { WordWrap = true } };
+ StackPanel row = new(Orientation.Horizontal);
+ row.AddChild(new TextElement("Label text here: "));
+ row.AddChild(border);
+ StackPanel panel = new(Orientation.Vertical);
+ panel.AddChild(row);
+ panel.AddChild(new TextElement("below"));
+ panel.Position = Position.Origin;
+ panel.Dimensions = new Dimensions(19, 20);
+ RecordingConsoleProvider provider = new();
+
+ panel.ArrangeChildren();
+ panel.Render(provider);
+
+ Assert.AreEqual(2, provider.WritesOf("below").Single().Position.Y);
+ }
+}
diff --git a/TUI/Elements/UIContainerBase.cs b/TUI/Elements/UIContainerBase.cs
index 15e5ba7..be4db3a 100644
--- a/TUI/Elements/UIContainerBase.cs
+++ b/TUI/Elements/UIContainerBase.cs
@@ -141,7 +141,16 @@ protected override Dimensions OnCalculateRequiredDimensions()
///
protected override Dimensions OnCalculateRequiredDimensions(int availableWidth)
{
- Dimensions requiredDimensions = OnCalculateRequiredDimensionsForChildren(Math.Max(0, availableWidth - Padding.Horizontal));
+ if (availableWidth > 0 && availableWidth <= Padding.Horizontal)
+ {
+ // The padding takes every column, so no child can be drawn. Measuring the children at
+ // width 0 would read as "no constraint", and a word-wrapped child would then claim its
+ // full unwrapped height in rows that never show, taking them from the siblings below
+ // (ktsu-dev/TUI#249, the container route to ktsu-dev/TUI#198).
+ return Dimensions.Empty.WithPadding(Padding);
+ }
+
+ Dimensions requiredDimensions = OnCalculateRequiredDimensionsForChildren(availableWidth - Padding.Horizontal);
return requiredDimensions.WithPadding(Padding);
}