diff --git a/bevy_kayak_ui/src/render/unified/font/extract.rs b/bevy_kayak_ui/src/render/unified/font/extract.rs
index 195e16e7769e4552e099c2df513f860fb1a6a024..5c8e9461ac77a48915353cfc00e58fc0187e3b02 100644
--- a/bevy_kayak_ui/src/render/unified/font/extract.rs
+++ b/bevy_kayak_ui/src/render/unified/font/extract.rs
@@ -4,6 +4,7 @@ use bevy::{
     sprite::Rect,
 };
 use kayak_core::render_primitive::RenderPrimitive;
+use kayak_core::styles::Edge;
 use kayak_font::{Alignment, CoordinateSystem, KayakFont};
 
 use crate::{
@@ -77,7 +78,7 @@ pub fn extract_texts(
                 z_index: layout.z_index,
                 quad_type: UIQuadType::Text,
                 type_index: 0,
-                border_radius: (0.0, 0.0, 0.0, 0.0),
+                border_radius: Edge::default(),
                 image: None,
                 uv_max: None,
                 uv_min: None,
diff --git a/bevy_kayak_ui/src/render/unified/mod.rs b/bevy_kayak_ui/src/render/unified/mod.rs
index 3400b0e499e19e893097a4a4e87b6818524207ab..0fd0946b691552fb4e37b0049bfaeb5c46be6aab 100644
--- a/bevy_kayak_ui/src/render/unified/mod.rs
+++ b/bevy_kayak_ui/src/render/unified/mod.rs
@@ -10,6 +10,7 @@ use bevy::{
     window::Windows,
 };
 use kayak_core::{render_primitive::RenderPrimitive, Binding, Bound};
+use kayak_core::styles::Edge;
 use kayak_font::KayakFont;
 
 use crate::{
@@ -129,7 +130,7 @@ pub fn extract(
                         font_handle: None,
                         quad_type: UIQuadType::Clip,
                         type_index: 0,
-                        border_radius: (0.0, 0.0, 0.0, 0.0),
+                        border_radius: Edge::default(),
                         image: None,
                         uv_min: None,
                         uv_max: None,
diff --git a/bevy_kayak_ui/src/render/unified/nine_patch/extract.rs b/bevy_kayak_ui/src/render/unified/nine_patch/extract.rs
index 7fd27af5ea901bd92280a289b87be1877deb10de..24b3d78938a61afff47c2e90f864aa09cfff273d 100644
--- a/bevy_kayak_ui/src/render/unified/nine_patch/extract.rs
+++ b/bevy_kayak_ui/src/render/unified/nine_patch/extract.rs
@@ -5,6 +5,7 @@ use bevy::{
     sprite::Rect,
 };
 use kayak_core::render_primitive::RenderPrimitive;
+use kayak_core::styles::Edge;
 
 use crate::{
     render::unified::pipeline::{ExtractQuadBundle, ExtractedQuad, UIQuadType},
@@ -60,7 +61,7 @@ pub fn extract_nine_patch(
         font_handle: None,
         quad_type: UIQuadType::Image,
         type_index: 0,
-        border_radius: (0.0, 0.0, 0.0, 0.0),
+        border_radius: Edge::default(),
         image: image_handle,
         uv_max: None,
         uv_min: None,
diff --git a/bevy_kayak_ui/src/render/unified/pipeline.rs b/bevy_kayak_ui/src/render/unified/pipeline.rs
index 5c5857ad9c33df06e72440ddae9acd4a6668e436..b897abe87a914b5053e0a4ef55fc8db4b6df7407 100644
--- a/bevy_kayak_ui/src/render/unified/pipeline.rs
+++ b/bevy_kayak_ui/src/render/unified/pipeline.rs
@@ -32,6 +32,7 @@ use bevy::{
     utils::HashMap,
 };
 use bytemuck::{Pod, Zeroable};
+use kayak_core::styles::Edge;
 use kayak_font::{
     bevy::{FontRenderingPipeline, FontTextureCache},
     KayakFont,
@@ -320,7 +321,7 @@ pub struct ExtractedQuad {
     pub font_handle: Option<Handle<KayakFont>>,
     pub quad_type: UIQuadType,
     pub type_index: u32,
-    pub border_radius: (f32, f32, f32, f32),
+    pub border_radius: Edge<f32>,
     pub image: Option<Handle<Image>>,
     pub uv_min: Option<Vec2>,
     pub uv_max: Option<Vec2>,
@@ -413,25 +414,25 @@ pub fn prepare_quads(
             uv_min.x,
             uv_max.y,
             extracted_sprite.char_id as f32,
-            extracted_sprite.border_radius.0,
+            extracted_sprite.border_radius.top,
         );
         let top_left = Vec4::new(
             uv_min.x,
             uv_min.y,
             extracted_sprite.char_id as f32,
-            extracted_sprite.border_radius.1,
+            extracted_sprite.border_radius.right,
         );
         let top_right = Vec4::new(
             uv_max.x,
             uv_min.y,
             extracted_sprite.char_id as f32,
-            extracted_sprite.border_radius.2,
+            extracted_sprite.border_radius.bottom,
         );
         let bottom_right = Vec4::new(
             uv_max.x,
             uv_max.y,
             extracted_sprite.char_id as f32,
-            extracted_sprite.border_radius.3,
+            extracted_sprite.border_radius.left,
         );
 
         let uvs: [[f32; 4]; 6] = [
diff --git a/bevy_kayak_ui/src/render/unified/quad/extract.rs b/bevy_kayak_ui/src/render/unified/quad/extract.rs
index 19fc6dabbf4e09bb6de07c9b3b52334a1660124d..b98c8e90377263e769813eb01256f0077833f7d8 100644
--- a/bevy_kayak_ui/src/render/unified/quad/extract.rs
+++ b/bevy_kayak_ui/src/render/unified/quad/extract.rs
@@ -25,12 +25,7 @@ pub fn extract_quads(render_primitive: &RenderPrimitive, dpi: f32) -> Vec<Extrac
         _ => panic!(""),
     };
 
-    border = (
-        border.0 * dpi,
-        border.1 * dpi,
-        border.2 * dpi,
-        border.3 * dpi,
-    );
+    border *= dpi;
 
     vec![
         // Border
@@ -59,10 +54,10 @@ pub fn extract_quads(render_primitive: &RenderPrimitive, dpi: f32) -> Vec<Extrac
         ExtractQuadBundle {
             extracted_quad: ExtractedQuad {
                 rect: Rect {
-                    min: Vec2::new(layout.posx + border.3, layout.posy + border.0),
+                    min: Vec2::new(layout.posx + border.left, layout.posy + border.top),
                     max: Vec2::new(
-                        (layout.posx + (layout.width * dpi)) - border.1,
-                        (layout.posy + (layout.height * dpi)) - border.2,
+                        (layout.posx + (layout.width * dpi)) - border.right,
+                        (layout.posy + (layout.height * dpi)) - border.bottom,
                     ),
                 },
                 color: to_bevy_color(&background_color),
diff --git a/examples/clipping.rs b/examples/clipping.rs
index e92f22a9866499e7ebaf8bdce11ab3fd331b6fcf..e5abfc62b9ce37a6c3f2d4ae78dc497cee2f59a1 100644
--- a/examples/clipping.rs
+++ b/examples/clipping.rs
@@ -5,9 +5,8 @@ use bevy::{
 };
 use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, ImageManager, UICameraBundle};
 use kayak_ui::core::{
-    layout_cache::Space,
     render,
-    styles::{Style, StyleProp, Units},
+    styles::{Edge, Style, StyleProp, Units},
     Index,
 };
 use kayak_ui::widgets::{App, Clip, NinePatch, Text};
@@ -58,12 +57,7 @@ Vestibulum rutrum imperdiet nisl, et consequat massa porttitor vel. Ut velit jus
             <App>
                 <NinePatch
                     styles={Some(nine_patch_styles)}
-                    border={Space {
-                        left: 30.0,
-                        right: 30.0,
-                        top: 30.0,
-                        bottom: 30.0,
-                    }}
+                    border={Edge::all(30.0)}
                     handle={panel_brown_handle}
                 >
                     <Clip styles={Some(clip_styles)}>
diff --git a/examples/full_ui.rs b/examples/full_ui.rs
index 3b3bc352dd56aaf9fd38436ea7487eca40edc1a5..672102354d34cd5654d8f5f23f35f156ac4f1314 100644
--- a/examples/full_ui.rs
+++ b/examples/full_ui.rs
@@ -5,9 +5,8 @@ use bevy::{
 };
 use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, ImageManager, UICameraBundle};
 use kayak_ui::core::{
-    layout_cache::Space,
     render, rsx,
-    styles::{LayoutType, Style, StyleProp, Units},
+    styles::{Edge, LayoutType, Style, StyleProp, Units},
     widget, Bound, Children, EventType, Index, MutableBound, OnEvent, WidgetProps,
 };
 use kayak_ui::widgets::{App, NinePatch, Text};
@@ -73,12 +72,7 @@ fn BlueButton(props: BlueButtonProps) {
     let children = props.get_children();
     rsx! {
         <NinePatch
-            border={Space {
-                left: 10.0,
-                right: 10.0,
-                top: 10.0,
-                bottom: 10.0,
-            }}
+            border={Edge::all(10.0)}
             handle={current_button_handle.get()}
             styles={Some(button_styles)}
             on_event={Some(on_event)}
@@ -135,12 +129,7 @@ fn startup(
             <App>
                 <NinePatch
                     styles={Some(nine_patch_styles)}
-                    border={Space {
-                        left: 30.0,
-                        right: 30.0,
-                        top: 30.0,
-                        bottom: 30.0,
-                    }}
+                    border={Edge::all(30.0)}
                     handle={panel_brown_handle}
                 >
                     <Text
diff --git a/examples/image.rs b/examples/image.rs
index ec63e3047ff299f299a67186d5cd374b6304a4b0..05a1029ab77492ab2c8d5f5d5ceca85461b2f368 100644
--- a/examples/image.rs
+++ b/examples/image.rs
@@ -3,7 +3,7 @@ use bevy::{
     window::WindowDescriptor,
     DefaultPlugins,
 };
-use kayak_core::styles::PositionType;
+use kayak_core::styles::{Edge, PositionType};
 use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle};
 use kayak_ui::core::{
     render,
@@ -27,7 +27,7 @@ fn startup(
             position_type: StyleProp::Value(PositionType::SelfDirected),
             left: StyleProp::Value(Units::Pixels(10.0)),
             top: StyleProp::Value(Units::Pixels(10.0)),
-            border_radius: StyleProp::Value((500.0, 500.0, 500.0, 500.0)),
+            border_radius: StyleProp::Value(Edge::all(500.0)),
             width: StyleProp::Value(Units::Pixels(200.0)),
             height: StyleProp::Value(Units::Pixels(182.0)),
             ..Style::default()
diff --git a/examples/nine_patch.rs b/examples/nine_patch.rs
index 0498f7aaf810ae640e9512c9d1805cb9ad17ef1c..d5c13d41130ddb2a8e39b278ee206ac9875585b7 100644
--- a/examples/nine_patch.rs
+++ b/examples/nine_patch.rs
@@ -5,9 +5,8 @@ use bevy::{
 };
 use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle};
 use kayak_ui::core::{
-    layout_cache::Space,
     render,
-    styles::{Style, StyleProp, Units},
+    styles::{Edge, Style, StyleProp, Units},
     Index,
 };
 use kayak_ui::widgets::{App, NinePatch};
@@ -56,12 +55,7 @@ fn startup(
             <App>
                 <NinePatch
                     styles={Some(nine_patch_styles)}
-                    border={Space {
-                        left: 15.0,
-                        right: 15.0,
-                        top: 15.0,
-                        bottom: 15.0,
-                    }}
+                    border={Edge::all(15.0)}
                     handle={ui_image_handle}
                 />
             </App>
diff --git a/examples/todo/add_button.rs b/examples/todo/add_button.rs
index 4e17f14f9ef86ff0830a9a662de64e3cbb250667..937da1e9b6bd60b9550e358463772851c73fa284 100644
--- a/examples/todo/add_button.rs
+++ b/examples/todo/add_button.rs
@@ -3,7 +3,7 @@ use kayak_ui::core::{
     color::Color,
     render_command::RenderCommand,
     rsx,
-    styles::{Style, StyleProp, Units},
+    styles::{Edge, Style, StyleProp, Units},
     use_state, widget, EventType, OnEvent, WidgetProps,
 };
 
@@ -30,7 +30,7 @@ pub fn AddButton(props: AddButtonProps) {
     });
 
     let background_styles = Some(Style {
-        border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
+        border_radius: StyleProp::Value(Edge::all(5.0)),
         background_color: StyleProp::Value(color),
         cursor: CursorIcon::Hand.into(),
         padding_left: StyleProp::Value(Units::Pixels(9.0)),
diff --git a/examples/todo/delete_button.rs b/examples/todo/delete_button.rs
index 99371b43820d3fd58cd83cb1b5725a60b815396a..53706c4f7599e91d0f367605ab01cbb990ca5b29 100644
--- a/examples/todo/delete_button.rs
+++ b/examples/todo/delete_button.rs
@@ -3,7 +3,7 @@ use kayak_ui::core::{
     color::Color,
     render_command::RenderCommand,
     rsx,
-    styles::{Style, StyleProp, Units},
+    styles::{Edge, Style, StyleProp, Units},
     use_state, widget, EventType, OnEvent, WidgetProps,
 };
 
@@ -31,7 +31,7 @@ pub fn DeleteButton(props: DeleteButtonProps) {
     });
 
     let background_styles = Some(Style {
-        border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
+        border_radius: StyleProp::Value(Edge::all(5.0)),
         background_color: StyleProp::Value(color),
         cursor: CursorIcon::Hand.into(),
         padding_left: StyleProp::Value(Units::Pixels(8.0)),
diff --git a/kayak_core/src/node.rs b/kayak_core/src/node.rs
index c5bb0a494db4e5934c6b8307568f0eead5cf3b8d..16d13666e7f9e3087eb8ca44d2ddbf4c9ee7f886 100644
--- a/kayak_core/src/node.rs
+++ b/kayak_core/src/node.rs
@@ -362,7 +362,7 @@ impl<'a> morphorm::Node<'a> for Index {
             if let Some(node) = node {
                 return match node.resolved_styles.border {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.3)),
+                    StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.left)),
                     _ => Some(morphorm::Units::Auto),
                 };
             }
@@ -375,7 +375,7 @@ impl<'a> morphorm::Node<'a> for Index {
             if let Some(node) = node {
                 return match node.resolved_styles.border {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.1)),
+                    StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.right)),
                     _ => Some(morphorm::Units::Auto),
                 };
             }
@@ -388,7 +388,7 @@ impl<'a> morphorm::Node<'a> for Index {
             if let Some(node) = node {
                 return match node.resolved_styles.border {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.0)),
+                    StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.top)),
                     _ => Some(morphorm::Units::Auto),
                 };
             }
@@ -401,7 +401,7 @@ impl<'a> morphorm::Node<'a> for Index {
             if let Some(node) = node {
                 return match node.resolved_styles.border {
                     StyleProp::Default => Some(morphorm::Units::Auto),
-                    StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.2)),
+                    StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.bottom)),
                     _ => Some(morphorm::Units::Auto),
                 };
             }
diff --git a/kayak_core/src/render_command.rs b/kayak_core/src/render_command.rs
index 79c151c3826a96d01877cd45613a3c3a2469e19f..8365e223933de70816ee257217933a55946ab388 100644
--- a/kayak_core/src/render_command.rs
+++ b/kayak_core/src/render_command.rs
@@ -1,4 +1,4 @@
-use crate::layout_cache::Space;
+use crate::styles::Edge;
 
 #[derive(Debug, Clone, PartialEq)]
 pub enum RenderCommand {
@@ -18,7 +18,7 @@ pub enum RenderCommand {
         handle: u16,
     },
     NinePatch {
-        border: Space,
+        border: Edge<f32>,
         handle: u16,
     },
 }
diff --git a/kayak_core/src/render_primitive.rs b/kayak_core/src/render_primitive.rs
index 7f0017ce6f924a16d2c08d4369ded5d81d340e2d..d54dde1e4fa43d985d06e612c31fbf57e9902323 100644
--- a/kayak_core/src/render_primitive.rs
+++ b/kayak_core/src/render_primitive.rs
@@ -1,8 +1,8 @@
 use crate::{
     color::Color,
-    layout_cache::{Rect, Space},
+    layout_cache::Rect,
     render_command::RenderCommand,
-    styles::{Style, StyleProp},
+    styles::{Edge, Style, StyleProp},
 };
 
 #[derive(Debug, Clone, PartialEq)]
@@ -15,8 +15,8 @@ pub enum RenderPrimitive {
         layout: Rect,
         background_color: Color,
         border_color: Color,
-        border: (f32, f32, f32, f32),
-        border_radius: (f32, f32, f32, f32),
+        border: Edge<f32>,
+        border_radius: Edge<f32>,
     },
     Text {
         color: Color,
@@ -28,12 +28,12 @@ pub enum RenderPrimitive {
         size: f32,
     },
     Image {
-        border_radius: (f32, f32, f32, f32),
+        border_radius: Edge<f32>,
         layout: Rect,
         handle: u16,
     },
     NinePatch {
-        border: Space,
+        border: Edge<f32>,
         layout: Rect,
         handle: u16,
     },
diff --git a/kayak_core/src/styles/edge.rs b/kayak_core/src/styles/edge.rs
new file mode 100644
index 0000000000000000000000000000000000000000..0e5cbba83b48f2ccff9d6f0a62c68377d214696c
--- /dev/null
+++ b/kayak_core/src/styles/edge.rs
@@ -0,0 +1,164 @@
+use std::ops::{Mul, MulAssign};
+
+/// A struct for defining properties related to the edges of widgets
+///
+/// This is useful for things like borders, padding, etc.
+#[derive(Debug, Default, Copy, Clone, PartialEq)]
+pub struct Edge<T> where T: Copy + Default + PartialEq {
+    /// The value of the top edge
+    pub top: T,
+    /// The value of the right edge
+    pub right: T,
+    /// The value of the bottom edge
+    pub bottom: T,
+    /// The value of the left edge
+    pub left: T,
+}
+
+impl<T> Edge<T> where T: Copy + Default + PartialEq {
+    /// Creates a new `Edge` with values individually specified for each edge
+    ///
+    /// # Arguments
+    ///
+    /// * `top`: The top edge value
+    /// * `right`: The right edge value
+    /// * `bottom`: The bottom edge value
+    /// * `left`: The left edge value
+    ///
+    pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
+        Self {
+            top,
+            right,
+            bottom,
+            left,
+        }
+    }
+
+    /// Creates a new `Edge` with matching vertical edges and matching horizontal edges
+    ///
+    /// # Arguments
+    ///
+    /// * `vertical`: The value of the vertical edges
+    /// * `horizontal`: The value of the horizontal edges
+    ///
+    pub fn axis(vertical: T, horizontal: T) -> Self {
+        Self {
+            top: vertical,
+            right: horizontal,
+            bottom: vertical,
+            left: horizontal,
+        }
+    }
+
+    /// Creates a new `Edge` with all edges having the same value
+    ///
+    /// # Arguments
+    ///
+    /// * `value`: The value of all edges
+    ///
+    pub fn all(value: T) -> Self {
+        Self {
+            top: value,
+            right: value,
+            bottom: value,
+            left: value,
+        }
+    }
+
+    /// Converts this `Edge` into a tuple matching `(Top, Right, Bottom, Left)`
+    pub fn into_tuple(self) -> (T, T, T, T) {
+        (self.top, self.right, self.bottom, self.left)
+    }
+}
+
+impl<T> From<Edge<T>> for (T, T, T, T) where T: Copy + Default + PartialEq {
+    fn from(edge: Edge<T>) -> Self {
+        edge.into_tuple()
+    }
+}
+
+impl<T> From<T> for Edge<T> where T: Copy + Default + PartialEq {
+    fn from(value: T) -> Self {
+        Edge::all(value)
+    }
+}
+
+impl<T> From<(T, T)> for Edge<T> where T: Copy + Default + PartialEq {
+    fn from(value: (T, T)) -> Self {
+        Edge::axis(value.0, value.1)
+    }
+}
+
+impl<T> From<(T, T, T, T)> for Edge<T> where T: Copy + Default + PartialEq {
+    fn from(value: (T, T, T, T)) -> Self {
+        Edge::new(value.0, value.1, value.2, value.3)
+    }
+}
+
+impl<T> Mul<T> for Edge<T> where T: Copy + Default + PartialEq + Mul<Output=T> {
+    type Output = Self;
+
+    fn mul(self, rhs: T) -> Self::Output {
+        Self {
+            top: self.top * rhs,
+            right: self.right * rhs,
+            bottom: self.bottom * rhs,
+            left: self.left * rhs,
+        }
+    }
+}
+
+impl<T> Mul<Edge<T>> for Edge<T> where T: Copy + Default + PartialEq + Mul<Output=T> {
+    type Output = Self;
+
+    fn mul(self, rhs: Edge<T>) -> Self::Output {
+        Self {
+            top: rhs.top * self.top,
+            right: rhs.right * self.right,
+            bottom: rhs.bottom * self.bottom,
+            left: rhs.left * self.left,
+        }
+    }
+}
+
+impl<T> MulAssign<T> for Edge<T> where T: Copy + Default + PartialEq + MulAssign {
+    fn mul_assign(&mut self, rhs: T) {
+        self.top *= rhs;
+        self.right *= rhs;
+        self.bottom *= rhs;
+        self.left *= rhs;
+    }
+}
+
+impl<T> MulAssign<Edge<T>> for Edge<T> where T: Copy + Default + PartialEq + MulAssign {
+    fn mul_assign(&mut self, rhs: Edge<T>) {
+        self.top *= rhs.top;
+        self.right *= rhs.right;
+        self.bottom *= rhs.bottom;
+        self.left *= rhs.left;
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::Edge;
+
+    #[test]
+    fn tuples_should_convert_to_edge() {
+        let expected = (1.0, 2.0, 3.0, 4.0);
+        let edge: Edge<f32> = expected.into();
+        assert_eq!(expected, edge.into_tuple());
+
+        let expected = (1.0, 2.0, 1.0, 2.0);
+        let edge: Edge<f32> = (expected.0, expected.1).into();
+        assert_eq!(expected, edge.into_tuple());
+
+        let expected = (1.0, 1.0, 1.0, 1.0);
+        let edge: Edge<f32> = (expected.0).into();
+        assert_eq!(expected, edge.into_tuple());
+
+        let expected = (1.0, 1.0, 1.0, 1.0);
+        let edge: Edge<f32> = expected.0.into();
+        assert_eq!(expected, edge.into_tuple());
+    }
+}
\ No newline at end of file
diff --git a/kayak_core/src/styles/mod.rs b/kayak_core/src/styles/mod.rs
index be3dd40fd8b62285bb5044b9c5497930f333ef0f..e12944e98e8605a9938b0b59356a613a27c4b1f6 100644
--- a/kayak_core/src/styles/mod.rs
+++ b/kayak_core/src/styles/mod.rs
@@ -1,6 +1,8 @@
+mod edge;
 mod option_ref;
 
 pub use morphorm::{LayoutType, PositionType, Units};
+pub use edge::Edge;
 
 use crate::cursor::PointerEvents;
 use crate::{color::Color, render_command::RenderCommand, CursorIcon};
@@ -141,8 +143,8 @@ define_styles! {
     pub struct Style {
         pub background_color : StyleProp<Color>,
         pub border_color: StyleProp<Color>,
-        pub border_radius: StyleProp<(f32, f32, f32, f32)>,
-        pub border: StyleProp<(f32, f32, f32, f32)>,
+        pub border_radius: StyleProp<Edge<f32>>,
+        pub border: StyleProp<Edge<f32>>,
         pub bottom: StyleProp<Units>,
         pub color: StyleProp<Color>,
         /// The spacing between child widgets along the horizontal axis
diff --git a/src/widgets/button.rs b/src/widgets/button.rs
index a0cf25f65da1da47eb5fe6418f844d7b5fe708af..91a489fc4c15ceab083f7485a466ad702973953c 100644
--- a/src/widgets/button.rs
+++ b/src/widgets/button.rs
@@ -1,7 +1,7 @@
 use crate::core::{
     render_command::RenderCommand,
     rsx,
-    styles::{Style, StyleProp, Units},
+    styles::{Edge, Style, StyleProp, Units},
     widget, Children, Color, Fragment, OnEvent, WidgetProps,
 };
 use kayak_core::CursorIcon;
@@ -48,7 +48,7 @@ pub fn Button(props: ButtonProps) {
             .with_style(&props.styles)
             .with_style(Style {
                 background_color: StyleProp::Value(Color::new(0.0781, 0.0898, 0.101, 1.0)),
-                border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
+                border_radius: StyleProp::Value(Edge::all(5.0)),
                 height: StyleProp::Value(Units::Pixels(45.0)),
                 padding_left: StyleProp::Value(Units::Stretch(1.0)),
                 padding_right: StyleProp::Value(Units::Stretch(1.0)),
diff --git a/src/widgets/inspector.rs b/src/widgets/inspector.rs
index 88350ec2a22bc5308d547e6e5f46969de7322002..e28a2fee86cd867835dcaa919a71ffff294694be 100644
--- a/src/widgets/inspector.rs
+++ b/src/widgets/inspector.rs
@@ -1,4 +1,4 @@
-use kayak_core::styles::{PositionType, Style, StyleProp, Units};
+use kayak_core::styles::{Edge, PositionType, Style, StyleProp, Units};
 use kayak_core::{Bound, Color, EventType, OnEvent, VecTracker};
 use kayak_render_macros::{constructor, use_state};
 
@@ -24,7 +24,7 @@ pub fn Inspector(props: InspectorProps) {
 
     let background_styles = Some(Style {
         background_color: StyleProp::Value(Color::new(0.125, 0.125, 0.125, 1.0)),
-        border_radius: StyleProp::Value((0.0, 0.0, 0.0, 0.0)),
+        border_radius: StyleProp::Value(Edge::all(0.0)),
         position_type: StyleProp::Value(PositionType::SelfDirected),
         left: StyleProp::Value(Units::Stretch(1.0)),
         top: StyleProp::Value(Units::Stretch(0.0)),
diff --git a/src/widgets/nine_patch.rs b/src/widgets/nine_patch.rs
index 21521847934e6c6319c5f4083fe81b19f853a6a2..610680583dff54c86afe794e10025a8782c19a8d 100644
--- a/src/widgets/nine_patch.rs
+++ b/src/widgets/nine_patch.rs
@@ -1,15 +1,14 @@
 use crate::core::{
-    layout_cache::Space,
     render_command::RenderCommand,
     rsx,
-    styles::{Style, StyleProp},
+    styles::{Edge, Style, StyleProp},
     widget, Children, OnEvent, WidgetProps,
 };
 
 #[derive(WidgetProps, Default, Debug, PartialEq, Clone)]
 pub struct NinePatchProps {
     pub handle: u16,
-    pub border: Space,
+    pub border: Edge<f32>,
     #[prop_field(Styles)]
     pub styles: Option<Style>,
     #[prop_field(Children)]
diff --git a/src/widgets/text_box.rs b/src/widgets/text_box.rs
index 457f9b7624cf66f09839ebe6c4948abbacd05494..2c5730033aa599ad970264730b592bec017e8a28 100644
--- a/src/widgets/text_box.rs
+++ b/src/widgets/text_box.rs
@@ -1,7 +1,7 @@
 use crate::core::{
     render_command::RenderCommand,
     rsx,
-    styles::{Style, Units},
+    styles::{Edge, Style, Units},
     widget, Bound, Children, Color, EventType, MutableBound, OnEvent, WidgetProps,
 };
 use kayak_core::CursorIcon;
@@ -102,7 +102,7 @@ pub fn TextBox(props: TextBoxProps) {
 
     let background_styles = Style {
         background_color: Color::new(0.176, 0.196, 0.215, 1.0).into(),
-        border_radius: (5.0, 5.0, 5.0, 5.0).into(),
+        border_radius: Edge::all(5.0).into(),
         height: Units::Pixels(26.0).into(),
         padding_left: Units::Pixels(5.0).into(),
         padding_right: Units::Pixels(5.0).into(),
diff --git a/src/widgets/window.rs b/src/widgets/window.rs
index f763dc22e7ad3eae4e7025b61883ff72002886b3..bfcab4fa59ee912f95059b4d89401d2a44c772fb 100644
--- a/src/widgets/window.rs
+++ b/src/widgets/window.rs
@@ -2,7 +2,7 @@ use crate::core::{
     color::Color,
     render_command::RenderCommand,
     rsx,
-    styles::{PositionType, Style, StyleProp, Units},
+    styles::{Edge, PositionType, Style, StyleProp, Units},
     use_state, widget, Children, EventType, OnEvent, WidgetProps,
 };
 use kayak_core::CursorIcon;
@@ -64,8 +64,8 @@ pub fn Window(props: WindowProps) {
     props.styles = Some(Style {
         background_color: StyleProp::Value(Color::new(0.125, 0.125, 0.125, 1.0)),
         border_color: StyleProp::Value(Color::new(0.0781, 0.0898, 0.101, 1.0)),
-        border: StyleProp::Value((4.0, 4.0, 4.0, 4.0)),
-        border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
+        border: StyleProp::Value(Edge::all(4.0)),
+        border_radius: StyleProp::Value(Edge::all(5.0)),
         render_command: StyleProp::Value(RenderCommand::Quad),
         position_type: StyleProp::Value(PositionType::SelfDirected),
         left: StyleProp::Value(Units::Pixels(pos.0)),
@@ -101,7 +101,7 @@ pub fn Window(props: WindowProps) {
 
     let title_background_styles = Style {
         background_color: StyleProp::Value(Color::new(0.0781, 0.0898, 0.101, 1.0)),
-        border_radius: StyleProp::Value((5.0, 0.0, 0.0, 5.0)),
+        border_radius: StyleProp::Value(Edge::all(5.0)),
         cursor: cursor.into(),
         height: StyleProp::Value(Units::Pixels(24.0)),
         width: StyleProp::Value(Units::Stretch(1.0)),