diff --git a/src/Perspex.Controls/Canvas.cs b/src/Perspex.Controls/Canvas.cs
new file mode 100644
index 0000000000..8751466464
--- /dev/null
+++ b/src/Perspex.Controls/Canvas.cs
@@ -0,0 +1,131 @@
+// Copyright (c) The Perspex Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+using Perspex.Input;
+
+namespace Perspex.Controls
+{
+ public class Canvas : Panel, INavigableContainer
+ {
+ ///
+ /// Defines the property.
+ ///
+ public static readonly PerspexProperty LeftProperty =
+ PerspexProperty.RegisterAttached("Left");
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly PerspexProperty TopProperty =
+ PerspexProperty.RegisterAttached("Top");
+
+ ///
+ /// Initializes static members of the class.
+ ///
+ static Canvas()
+ {
+ AffectsArrange(LeftProperty);
+ AffectsArrange(TopProperty);
+ }
+
+ ///
+ /// Gets the value of the Left attached property for a control.
+ ///
+ /// The control.
+ /// The control's left coordinate.
+ public static double GetLeft(PerspexObject element)
+ {
+ return element.GetValue(LeftProperty);
+ }
+
+ ///
+ /// Sets the value of the Left attached property for a control.
+ ///
+ /// The control.
+ /// The left value.
+ public static void SetLeft(PerspexObject element, double value)
+ {
+ element.SetValue(LeftProperty, value);
+ }
+
+ ///
+ /// Gets the value of the Top attached property for a control.
+ ///
+ /// The control.
+ /// The control's top coordinate.
+ public static double GetTop(PerspexObject element)
+ {
+ return element.GetValue(TopProperty);
+ }
+
+ ///
+ /// Sets the value of the Top attached property for a control.
+ ///
+ /// The control.
+ /// The top value.
+ public static void SetTop(PerspexObject element, double value)
+ {
+ element.SetValue(TopProperty, value);
+ }
+
+ ///
+ /// Gets the next control in the specified direction.
+ ///
+ /// The movement direction.
+ /// The control from which movement begins.
+ /// The control.
+ IInputElement INavigableContainer.GetControl(FocusNavigationDirection direction, IInputElement from)
+ {
+ // TODO: Implement this
+ return null;
+ }
+
+ ///
+ /// Measures the control.
+ ///
+ /// The available size.
+ /// The desired size of the control.
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
+
+ foreach (Control child in Children)
+ {
+ child.Measure(availableSize);
+ }
+
+ return new Size();
+ }
+
+ ///
+ /// Arranges the control's children.
+ ///
+ /// The size allocated to the control.
+ /// The space taken.
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ foreach (Control child in Children)
+ {
+ double x = 0.0;
+ double y = 0.0;
+ double elementLeft = GetLeft(child);
+
+ if (double.IsNaN(elementLeft) == false)
+ {
+ x = elementLeft;
+ }
+
+ double elementTop = GetTop(child);
+ if (double.IsNaN(elementTop) == false)
+ {
+ y = elementTop;
+ }
+
+ child.Arrange(new Rect(new Point(x, y), child.DesiredSize));
+ }
+
+ return finalSize;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Perspex.Controls/Perspex.Controls.csproj b/src/Perspex.Controls/Perspex.Controls.csproj
index dc7cbc571a..eaebc6aae6 100644
--- a/src/Perspex.Controls/Perspex.Controls.csproj
+++ b/src/Perspex.Controls/Perspex.Controls.csproj
@@ -65,6 +65,7 @@
+