diff --git a/examples/layout.rs b/examples/layout.rs
new file mode 100644
index 0000000000000000000000000000000000000000..41e335a54a0255ba8db2998b4a4468d87c91f3a9
--- /dev/null
+++ b/examples/layout.rs
@@ -0,0 +1,143 @@
+use bevy::prelude::*;
+use kayak_ui::prelude::{widgets::*, *};
+
+fn startup(
+    mut commands: Commands,
+    mut font_mapping: ResMut<FontMapping>,
+    asset_server: Res<AssetServer>,
+) {
+    font_mapping.set_default(asset_server.load("roboto.kayak_font"));
+
+    // Camera 2D forces a clear pass in bevy.
+    // We do this because our scene is not rendering anything else.
+    commands.spawn(Camera2dBundle::default());
+
+    let mut widget_context = KayakRootContext::new();
+    widget_context.add_plugin(KayakWidgetsContextPlugin);
+    let parent_id = None;
+
+    rsx! {
+        <KayakAppBundle>
+            <WindowBundle
+                window={KWindow {
+                    title: "Layout example".into(),
+                    draggable: true,
+                    initial_position: Vec2::new(10.0, 10.0),
+                    size: Vec2::new(512.0, 512.0),
+                    ..KWindow::default()
+                }}
+            >
+                <ElementBundle
+                    styles={KStyle{
+                        layout_type: LayoutType::Grid.into(),
+                        grid_rows: vec![Units::Stretch(1.0), Units::Stretch(2.0), Units::Stretch(5.0)].into(),
+                        grid_cols: vec![Units::Stretch(1.0), Units::Stretch(1.0)].into(),
+                        ..default()
+                    }}
+                >
+                    <BackgroundBundle
+                        styles={KStyle{
+                            background_color: Color::rgb(0.4, 0.9, 0.4).into(),
+                            color: Color::rgb(0.0, 0.0, 0.0).into(),
+                            padding: Edge::all(Units::Pixels(5.0)).into(),
+                            border_radius: Corner::all(10.0).into(),
+                            row_index: 0.into(),
+                            col_index: 0.into(),
+                            col_span: 2.into(),
+                            layout_type: LayoutType::Row.into(),
+                            col_between: Units::Pixels(5.0).into(),
+                            ..default()
+                        }}
+                    >
+                        <TextWidgetBundle
+                            text={TextProps {
+                                content: "A".into(),
+                                ..default()
+                            }}
+                        />
+                        <TextWidgetBundle
+                            text={TextProps {
+                                content: "B".into(),
+                                ..default()
+                            }}
+                        />
+                        <TextWidgetBundle
+                            text={TextProps {
+                                content: "C".into(),
+                                ..default()
+                            }}
+                        />
+                        <TextWidgetBundle
+                            text={TextProps {
+                                content: "D".into(),
+                                ..default()
+                            }}
+                        />
+                        <TextWidgetBundle
+                            text={TextProps {
+                                content: "E".into(),
+                                ..default()
+                            }}
+                        />
+
+                    </BackgroundBundle>
+                    <TextWidgetBundle
+                        text={TextProps {
+                            content: "R1 C0".into(),
+                            ..default()
+                        }}
+                        styles={KStyle{
+                            row_index: 1.into(),
+                            col_index: 0.into(),
+                            ..default()
+                        }}
+                    />
+                    <TextWidgetBundle
+                        text={TextProps {
+                            content: "R1 C1".into(),
+                            ..default()
+                        }}
+                        styles={KStyle{
+                            row_index: 1.into(),
+                            col_index: 1.into(),
+                            ..default()
+                        }}
+                    />
+                    <TextWidgetBundle
+                        text={TextProps {
+                            content: "R2 C0".into(),
+                            ..default()
+                        }}
+                        styles={KStyle{
+                            row_index: 2.into(),
+                            col_index: 0.into(),
+                            ..default()
+                        }}
+                    />
+                    <TextWidgetBundle
+                        text={TextProps {
+                            content: "R2 C1".into(),
+                            ..default()
+                        }}
+                        styles={KStyle{
+                            row_index: 2.into(),
+                            col_index: 1.into(),
+                            ..default()
+                        }}
+                    />
+                </ElementBundle>
+            </WindowBundle>
+        </KayakAppBundle>
+    }
+
+    commands.spawn(UICameraBundle::new(widget_context));
+}
+
+fn main() {
+    App::new()
+        .add_plugins(DefaultPlugins)
+        .add_plugin(KayakContextPlugin)
+        .add_plugin(KayakWidgets)
+        .add_startup_system(startup)
+        .run()
+}
diff --git a/src/node.rs b/src/node.rs
index 9c655a2613d988c6712df13a0f1fa37c8ebc1f8f..b307207fa7cff0b66674aed8b3d568aa8986726e 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -379,27 +379,69 @@ impl<'a> morphorm::Node<'a> for WrappedIndex {
         Some(morphorm::Units::Auto)
     }
 
-    fn grid_rows(&self, _store: &'_ Self::Data) -> Option<Vec<morphorm::Units>> {
+    fn grid_rows(&self, store: &'_ Self::Data) -> Option<Vec<morphorm::Units>> {
+        if let Ok(node) = store.get(self.0) {
+            return match &node.resolved_styles.grid_rows {
+                StyleProp::Default => Some(vec![]),
+                StyleProp::Value(prop) => Some(prop.iter().map(|&x| x.into()).collect()),
+                _ => Some(vec![]),
+            };
+        }
         Some(vec![])
     }
 
-    fn grid_cols(&self, _store: &'_ Self::Data) -> Option<Vec<morphorm::Units>> {
+    fn grid_cols(&self, store: &'_ Self::Data) -> Option<Vec<morphorm::Units>> {
+        if let Ok(node) = store.get(self.0) {
+            return match &node.resolved_styles.grid_cols {
+                StyleProp::Default => Some(vec![]),
+                StyleProp::Value(prop) => Some(prop.iter().map(|&x| x.into()).collect()),
+                _ => Some(vec![]),
+            };
+        }
         Some(vec![])
     }
 
-    fn row_index(&self, _store: &'_ Self::Data) -> Option<usize> {
+    fn row_index(&self, store: &'_ Self::Data) -> Option<usize> {
+        if let Ok(node) = store.get(self.0) {
+            return match node.resolved_styles.row_index {
+                StyleProp::Default => Some(0),
+                StyleProp::Value(prop) => Some(prop),
+                _ => Some(0),
+            };
+        }
         Some(0)
     }
 
-    fn col_index(&self, _store: &'_ Self::Data) -> Option<usize> {
+    fn col_index(&self, store: &'_ Self::Data) -> Option<usize> {
+        if let Ok(node) = store.get(self.0) {
+            return match node.resolved_styles.col_index {
+                StyleProp::Default => Some(0),
+                StyleProp::Value(prop) => Some(prop),
+                _ => Some(0),
+            };
+        }
         Some(0)
     }
 
-    fn row_span(&self, _store: &'_ Self::Data) -> Option<usize> {
+    fn row_span(&self, store: &'_ Self::Data) -> Option<usize> {
+        if let Ok(node) = store.get(self.0) {
+            return match node.resolved_styles.row_span {
+                StyleProp::Default => Some(1),
+                StyleProp::Value(prop) => Some(prop),
+                _ => Some(1),
+            };
+        }
         Some(1)
     }
 
-    fn col_span(&self, _store: &'_ Self::Data) -> Option<usize> {
+    fn col_span(&self, store: &'_ Self::Data) -> Option<usize> {
+        if let Ok(node) = store.get(self.0) {
+            return match node.resolved_styles.col_span {
+                StyleProp::Default => Some(1),
+                StyleProp::Value(prop) => Some(prop),
+                _ => Some(1),
+            };
+        }
         Some(1)
     }
 
diff --git a/src/styles/style.rs b/src/styles/style.rs
index 70b7f8f17344d4dd1e606ca5530f1cc5c4095bbe..5dba8472a8c1905b4f4637750b0708b0cce3f199 100644
--- a/src/styles/style.rs
+++ b/src/styles/style.rs
@@ -374,6 +374,30 @@ define_styles! {
         pub width: StyleProp<Units>,
         /// The z-index relative to it's parent.
         pub z_index: StyleProp<i32>,
+        /// The list of rows when using the grid layout
+        ///
+        /// This is specified in the parent widget and the children have to specify their `row_index`.
+        pub grid_rows: StyleProp<Vec<Units>>,
+        /// The list of columns when using the grid layout
+        ///
+        /// This is specified in the parent widget and the children have to specify their `col_index`.
+        pub grid_cols: StyleProp<Vec<Units>>,
+        /// The row index of this widget when using the grid layout
+        ///
+        /// This references the `grid_rows` property of the parent widget.
+        pub row_index: StyleProp<usize>,
+        /// The column index of this widget when using the grid layout
+        ///
+        /// This references the `grid_cols` property of the parent widget.
+        pub col_index: StyleProp<usize>,
+        /// The number rows that this widget spans when using the grid layout
+        ///
+        /// Specified in the child widget.
+        pub row_span: StyleProp<usize>,
+        /// The number columns that this widget spans when using the grid layout
+        ///
+        /// Specified in the child widget.
+        pub col_span: StyleProp<usize>,
     }
 }
 
@@ -416,6 +440,12 @@ impl KStyle {
             top: StyleProp::Default,
             width: StyleProp::Default,
             z_index: StyleProp::Default,
+            grid_rows: StyleProp::Default,
+            grid_cols: StyleProp::Default,
+            row_index: StyleProp::Default,
+            col_index: StyleProp::Default,
+            row_span: StyleProp::Default,
+            col_span: StyleProp::Default,
         }
     }
 }