diff --git a/TUI.Test/UIContainerBaseMeasureTests.cs b/TUI.Test/UIContainerBaseMeasureTests.cs
new file mode 100644
index 0000000..70cb036
--- /dev/null
+++ b/TUI.Test/UIContainerBaseMeasureTests.cs
@@ -0,0 +1,67 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+
+namespace ktsu.TUI.Test;
+
+using ktsu.TUI.Core.Contracts;
+using ktsu.TUI.Core.Elements;
+using ktsu.TUI.Core.Elements.Primitives;
+using ktsu.TUI.Core.Models;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+///
+/// Tests for the default measurement a custom container inherits from UIContainerBase
+///
+[TestClass]
+public sealed class UIContainerBaseMeasureTests
+{
+ ///
+ /// A container that places every child at its content origin and keeps the default measurement
+ ///
+ private sealed class OriginContainer : UIContainerBase
+ {
+ protected override void OnRender(IConsoleProvider provider) { }
+
+ protected override void OnArrangeChildren()
+ {
+ foreach (IUIElement child in GetVisibleChildren())
+ {
+ child.Position = GetContentPosition();
+ }
+ }
+ }
+
+ private static OriginContainer CreateContainer(Position position)
+ {
+ OriginContainer container = new()
+ {
+ Position = position,
+ Padding = Padding.Uniform(1),
+ };
+ container.AddChild(new TextElement { Text = "abc" });
+ container.ArrangeChildren();
+ return container;
+ }
+
+ ///
+ /// The required size is the content plus one padding, not the screen position plus two paddings
+ ///
+ [TestMethod]
+ public void DefaultMeasurementIsContentPlusPadding()
+ {
+ OriginContainer container = CreateContainer(new Position(10, 5));
+
+ Assert.AreEqual(new Dimensions(5, 3), container.CalculateRequiredDimensions());
+ }
+
+ ///
+ /// Moving the container on screen does not change how large it asks to be
+ ///
+ [TestMethod]
+ public void DefaultMeasurementDoesNotDependOnPosition()
+ {
+ Dimensions atOrigin = CreateContainer(Position.Origin).CalculateRequiredDimensions();
+ Dimensions elsewhere = CreateContainer(new Position(40, 12)).CalculateRequiredDimensions();
+
+ Assert.AreEqual(atOrigin, elsewhere);
+ }
+}
diff --git a/TUI/Elements/UIContainerBase.cs b/TUI/Elements/UIContainerBase.cs
index ed7e5a7..306c05d 100644
--- a/TUI/Elements/UIContainerBase.cs
+++ b/TUI/Elements/UIContainerBase.cs
@@ -132,14 +132,17 @@ protected virtual Dimensions OnCalculateRequiredDimensionsForChildren()
return Dimensions.Empty;
}
+ // Children sit at absolute screen positions, so measure them from the content origin; the
+ // container's own position and padding are not part of the content's size
+ Position origin = GetContentPosition();
int maxWidth = 0;
int maxHeight = 0;
foreach (IUIElement child in _children)
{
Dimensions childDimensions = child.CalculateRequiredDimensions();
- int childRight = child.Position.X + childDimensions.Width;
- int childBottom = child.Position.Y + childDimensions.Height;
+ int childRight = Math.Max(0, child.Position.X - origin.X + childDimensions.Width);
+ int childBottom = Math.Max(0, child.Position.Y - origin.Y + childDimensions.Height);
maxWidth = Math.Max(maxWidth, childRight);
maxHeight = Math.Max(maxHeight, childBottom);