diff --git a/src/elements/code.rs b/src/elements/code.rs
index 0ebb050..06e5c66 100644
--- a/src/elements/code.rs
+++ b/src/elements/code.rs
@@ -325,7 +325,7 @@ impl CodeRule {
 				)
 				.unwrap(),
 			],
-			properties: PropertyParser::new(props),
+			properties: PropertyParser{ properties: props },
 		}
 	}
 }
diff --git a/src/elements/graphviz.rs b/src/elements/graphviz.rs
index f2cbdc9..b2d3586 100644
--- a/src/elements/graphviz.rs
+++ b/src/elements/graphviz.rs
@@ -179,7 +179,7 @@ impl GraphRule {
 				r"\[graph\](?:\[((?:\\.|[^\[\]\\])*?)\])?(?:((?:\\.|[^\\\\])*?)\[/graph\])?",
 			)
 			.unwrap()],
-			properties: PropertyParser::new(props),
+			properties: PropertyParser{ properties: props },
 		}
 	}
 }
diff --git a/src/elements/layout.rs b/src/elements/layout.rs
index abfaa57..d1a17d8 100644
--- a/src/elements/layout.rs
+++ b/src/elements/layout.rs
@@ -4,11 +4,13 @@ use crate::document::document::Document;
 use crate::document::element::ElemKind;
 use crate::document::element::Element;
 use crate::parser::parser::Parser;
+use crate::parser::parser::ReportColors;
 use crate::parser::rule::RegexRule;
 use crate::parser::source::Source;
 use crate::parser::source::Token;
 use crate::parser::state::Scope;
 use crate::parser::state::State;
+use crate::parser::util::process_escaped;
 use ariadne::Fmt;
 use ariadne::Label;
 use ariadne::Report;
@@ -17,7 +19,9 @@ use lazy_static::lazy_static;
 use mlua::Function;
 use mlua::Lua;
 use regex::Captures;
+use regex::Match;
 use regex::Regex;
+use std::any::Any;
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::ops::Range;
@@ -35,6 +39,9 @@ pub trait LayoutType: core::fmt::Debug {
 	/// Name of the layout
 	fn name(&self) -> &'static str;
 
+	/// Parses layout properties
+	fn parse_properties(&self, properties: &str) -> Result<Option<Box<dyn Any>>, String>;
+
 	/// Expected number of blocks
 	fn expects(&self) -> Range<usize>;
 
@@ -43,15 +50,21 @@ pub trait LayoutType: core::fmt::Debug {
 		&self,
 		token: LayoutToken,
 		id: usize,
+		properties: &Option<Box<dyn Any>>,
 		compiler: &Compiler,
 		document: &dyn Document,
 	) -> Result<String, String>;
 }
 
 mod default_layouts {
+	use std::any::Any;
+
+	use crate::parser::util::Property;
+	use crate::parser::util::PropertyParser;
+
 	use super::*;
 
-	#[derive(Debug)]
+	#[derive(Debug, Default)]
 	pub struct Centered;
 
 	impl LayoutType for Centered {
@@ -59,10 +72,18 @@ mod default_layouts {
 
 		fn expects(&self) -> Range<usize> { 1..1 }
 
+		fn parse_properties(&self, properties: &str) -> Result<Option<Box<dyn Any>>, String> {
+			if !properties.is_empty() {
+				return Err(format!("Layout {} excepts no properties", self.name()));
+			}
+			Ok(None)
+		}
+
 		fn compile(
 			&self,
 			token: LayoutToken,
 			_id: usize,
+			_properties: &Option<Box<dyn Any>>,
 			compiler: &Compiler,
 			_document: &dyn Document,
 		) -> Result<String, String> {
@@ -78,26 +99,83 @@ mod default_layouts {
 	}
 
 	#[derive(Debug)]
-	pub struct Split;
+	pub struct Split {
+		properties: PropertyParser,
+	}
+
+	impl Default for Split {
+		fn default() -> Self {
+			let mut properties = HashMap::new();
+			properties.insert(
+				"style".to_string(),
+				Property::new(
+					true,
+					"Additional style for the split".to_string(),
+					Some("".to_string()),
+				),
+			);
+
+			Self {
+				properties: PropertyParser { properties },
+			}
+		}
+	}
 
 	impl LayoutType for Split {
 		fn name(&self) -> &'static str { "Split" }
 
-		fn expects(&self) -> Range<usize> { 2..usize::MAX  }
+		fn expects(&self) -> Range<usize> { 2..usize::MAX }
+
+		fn parse_properties(&self, properties: &str) -> Result<Option<Box<dyn Any>>, String> {
+			let props = if properties.is_empty() {
+				self.properties.default()
+			} else {
+				self.properties.parse(properties)
+			}
+			.map_err(|err| {
+				format!(
+					"Failed to parse properties for layout {}: {err}",
+					self.name()
+				)
+			})?;
+
+			let style = props
+				.get("style", |_, value| -> Result<String, ()> {
+					Ok(value.clone())
+				})
+				.map_err(|err| format!("Failed to parse style: {err:#?}"))
+				.map(|(_, value)| value)?;
+
+			Ok(Some(Box::new(style)))
+		}
 
 		fn compile(
 			&self,
 			token: LayoutToken,
 			_id: usize,
+			properties: &Option<Box<dyn Any>>,
 			compiler: &Compiler,
 			_document: &dyn Document,
 		) -> Result<String, String> {
 			match compiler.target() {
-				Target::HTML => match token {
-					LayoutToken::BEGIN => Ok(r#"<div class="split-container"><div class="split">"#.to_string()),
-					LayoutToken::NEXT => Ok(r#"</div><div class="split">"#.to_string()),
-					LayoutToken::END => Ok(r#"</div></div>"#.to_string()),
-				},
+				Target::HTML => {
+					let style = match properties
+						.as_ref()
+						.unwrap()
+						.downcast_ref::<String>()
+						.unwrap().as_str()
+						{
+							"" => "".to_string(),
+							str => format!(r#" style={}"#, Compiler::sanitize(compiler.target(), str))
+						};
+					match token {
+						LayoutToken::BEGIN => Ok(format!(
+							r#"<div class="split-container"><div class="split"{style}>"#
+						)),
+						LayoutToken::NEXT => Ok(format!(r#"</div><div class="split"{style}>"#)),
+						LayoutToken::END => Ok(r#"</div></div>"#.to_string()),
+					}
+				}
 				_ => todo!(""),
 			}
 		}
@@ -110,6 +188,7 @@ struct Layout {
 	pub(self) layout: Rc<dyn LayoutType>,
 	pub(self) id: usize,
 	pub(self) token: LayoutToken,
+	pub(self) properties: Option<Box<dyn Any>>,
 }
 
 impl Element for Layout {
@@ -118,7 +197,8 @@ impl Element for Layout {
 	fn element_name(&self) -> &'static str { "Layout" }
 	fn to_string(&self) -> String { format!("{self:#?}") }
 	fn compile(&self, compiler: &Compiler, document: &dyn Document) -> Result<String, String> {
-		self.layout.compile(self.token, self.id, compiler, document)
+		self.layout
+			.compile(self.token, self.id, &self.properties, compiler, document)
 	}
 }
 
@@ -182,20 +262,64 @@ pub struct LayoutRule {
 impl LayoutRule {
 	pub fn new() -> Self {
 		let mut layouts: HashMap<String, Rc<dyn LayoutType>> = HashMap::new();
-		let layout_centered = default_layouts::Centered {};
+
+		let layout_centered = default_layouts::Centered::default();
 		layouts.insert(layout_centered.name().to_string(), Rc::new(layout_centered));
-		let layout_split = default_layouts::Split {};
+
+		let layout_split = default_layouts::Split::default();
 		layouts.insert(layout_split.name().to_string(), Rc::new(layout_split));
 
 		Self {
 			re: [
-				Regex::new(r"(?:^|\n)#\+LAYOUT_BEGIN(.*)").unwrap(),
-				Regex::new(r"(?:^|\n)#\+LAYOUT_NEXT(?:$|\n)").unwrap(),
-				Regex::new(r"(?:^|\n)#\+LAYOUT_END(?:$|\n)").unwrap(),
+				Regex::new(r"(?:^|\n)#\+LAYOUT_BEGIN(?:\[((?:\\.|[^\\\\])*?)\])?(.*)").unwrap(),
+				Regex::new(r"(?:^|\n)#\+LAYOUT_NEXT(?:\[((?:\\.|[^\\\\])*?)\])?(?:$|\n)").unwrap(),
+				Regex::new(r"(?:^|\n)#\+LAYOUT_END(?:\[((?:\\.|[^\\\\])*?)\])?(?:$|\n)").unwrap(),
 			],
 			layouts,
 		}
 	}
+
+	pub fn parse_properties<'a>(
+		colors: &ReportColors,
+		token: &Token,
+		layout_type: Rc<dyn LayoutType>,
+		properties: Option<Match>,
+	) -> Result<Option<Box<dyn Any>>, Report<'a, (Rc<dyn Source>, Range<usize>)>> {
+		match properties {
+			None => match layout_type.parse_properties("") {
+				Ok(props) => Ok(props),
+				Err(err) => Err(
+					Report::build(ReportKind::Error, token.source(), token.start())
+						.with_message("Unable to parse layout properties")
+						.with_label(
+							Label::new((token.source(), token.range.clone()))
+								.with_message(err)
+								.with_color(colors.error),
+						)
+						.finish(),
+				),
+			},
+			Some(props) => {
+				let trimmed = props.as_str().trim_start().trim_end();
+				let content = process_escaped('\\', "]", trimmed);
+				match layout_type.parse_properties(content.as_str()) {
+					Ok(props) => Ok(props),
+					Err(err) => {
+						Err(
+							Report::build(ReportKind::Error, token.source(), props.start())
+								.with_message("Unable to parse layout properties")
+								.with_label(
+									Label::new((token.source(), props.range()))
+										.with_message(err)
+										.with_color(colors.error),
+								)
+								.finish(),
+						)
+					}
+				}
+			}
+		}
+	}
 }
 
 lazy_static! {
@@ -235,7 +359,7 @@ impl RegexRule for LayoutRule {
 		if index == 0
 		// BEGIN_LAYOUT
 		{
-			match matches.get(1) {
+			match matches.get(2) {
 				None => {
 					reports.push(
 						Report::build(ReportKind::Error, token.source(), token.start())
@@ -276,11 +400,11 @@ impl RegexRule for LayoutRule {
 					{
 						reports.push(
 							Report::build(ReportKind::Error, token.source(), name.start())
-								.with_message("Empty Layout Name")
+								.with_message("Invalid Layout Name")
 								.with_label(
 									Label::new((token.source(), name.range()))
 										.with_message(format!(
-											"Missing a space before layout `{}`",
+											"Missing a space before layout name `{}`",
 											name.as_str().fg(parser.colors().highlight)
 										))
 										.with_color(parser.colors().error),
@@ -311,6 +435,20 @@ impl RegexRule for LayoutRule {
 						Some(layout_type) => layout_type,
 					};
 
+					// Parse properties
+					let properties = match LayoutRule::parse_properties(
+						parser.colors(),
+						&token,
+						layout_type.clone(),
+						matches.get(1),
+					) {
+						Ok(props) => props,
+						Err(rep) => {
+							reports.push(rep);
+							return reports;
+						}
+					};
+
 					parser.push(
 						document,
 						Box::new(Layout {
@@ -318,6 +456,7 @@ impl RegexRule for LayoutRule {
 							layout: layout_type.clone(),
 							id: 0,
 							token: LayoutToken::BEGIN,
+							properties,
 						}),
 					);
 
@@ -333,7 +472,7 @@ impl RegexRule for LayoutRule {
 			return reports;
 		}
 
-		let (id, token_type, layout_type) = if index == 1
+		let (id, token_type, layout_type, properties) = if index == 1
 		// LAYOUT_NEXT
 		{
 			let mut state_borrow = state.borrow_mut();
@@ -376,8 +515,27 @@ impl RegexRule for LayoutRule {
 				return reports;
 			}
 
+			// Parse properties
+			let properties = match LayoutRule::parse_properties(
+				parser.colors(),
+				&token,
+				layout_type.clone(),
+				matches.get(1),
+			) {
+				Ok(props) => props,
+				Err(rep) => {
+					reports.push(rep);
+					return reports;
+				}
+			};
+
 			tokens.push(token.clone());
-			(tokens.len() - 1, LayoutToken::NEXT, layout_type.clone())
+			(
+				tokens.len() - 1,
+				LayoutToken::NEXT,
+				layout_type.clone(),
+				properties,
+			)
 		} else {
 			// LAYOUT_END
 			let mut state_borrow = state.borrow_mut();
@@ -420,10 +578,24 @@ impl RegexRule for LayoutRule {
 				return reports;
 			}
 
+			// Parse properties
+			let properties = match LayoutRule::parse_properties(
+				parser.colors(),
+				&token,
+				layout_type.clone(),
+				matches.get(1),
+			) {
+				Ok(props) => props,
+				Err(rep) => {
+					reports.push(rep);
+					return reports;
+				}
+			};
+
 			let layout_type = layout_type.clone();
 			let id = tokens.len();
 			state.stack.pop();
-			(id, LayoutToken::END, layout_type)
+			(id, LayoutToken::END, layout_type, properties)
 		};
 
 		parser.push(
@@ -433,6 +605,7 @@ impl RegexRule for LayoutRule {
 				layout: layout_type,
 				id,
 				token: token_type,
+				properties,
 			}),
 		);
 
diff --git a/src/elements/media.rs b/src/elements/media.rs
index f7e4b23..ee03396 100644
--- a/src/elements/media.rs
+++ b/src/elements/media.rs
@@ -258,7 +258,7 @@ impl MediaRule {
 			.multi_line(true)
 			.build()
 			.unwrap()],
-			properties: PropertyParser::new(props),
+			properties: PropertyParser{ properties: props },
 		}
 	}
 
diff --git a/src/elements/raw.rs b/src/elements/raw.rs
index 32ba94f..d6f95d0 100644
--- a/src/elements/raw.rs
+++ b/src/elements/raw.rs
@@ -67,7 +67,7 @@ impl RawRule {
 				Regex::new(r"\{\?(?:\[((?:\\.|[^\[\]\\])*?)\])?(?:((?:\\.|[^\\\\])*?)(\?\}))?")
 					.unwrap(),
 			],
-			properties: PropertyParser::new(props),
+			properties: PropertyParser{ properties: props },
 		}
 	}
 }
diff --git a/src/elements/reference.rs b/src/elements/reference.rs
index e467fc9..e5cf754 100644
--- a/src/elements/reference.rs
+++ b/src/elements/reference.rs
@@ -84,7 +84,7 @@ impl ReferenceRule {
 		);
 		Self {
 			re: [Regex::new(r"ยง\{(.*)\}(\[((?:\\.|[^\\\\])*?)\])?").unwrap()],
-			properties: PropertyParser::new(props),
+			properties: PropertyParser{ properties: props },
 		}
 	}
 
diff --git a/src/elements/tex.rs b/src/elements/tex.rs
index e2a7708..58f58ae 100644
--- a/src/elements/tex.rs
+++ b/src/elements/tex.rs
@@ -253,7 +253,7 @@ impl TexRule {
 					.unwrap(),
 				Regex::new(r"\$(?:\[((?:\\.|[^\\\\])*?)\])?(?:((?:\\.|[^\\\\])*?)\$)?").unwrap(),
 			],
-			properties: PropertyParser::new(props),
+			properties: PropertyParser{ properties: props },
 		}
 	}
 
diff --git a/src/parser/util.rs b/src/parser/util.rs
index b89bf70..845013b 100644
--- a/src/parser/util.rs
+++ b/src/parser/util.rs
@@ -229,13 +229,12 @@ impl<'a> PropertyMap<'a> {
 	}
 }
 
+#[derive(Debug)]
 pub struct PropertyParser {
-	properties: HashMap<String, Property>,
+	pub properties: HashMap<String, Property>,
 }
 
 impl PropertyParser {
-	pub fn new(properties: HashMap<String, Property>) -> Self { Self { properties } }
-
 	/// Attempts to build a default propertymap
 	///
 	/// Returns an error if at least one [`Property`] is required and doesn't provide a default
@@ -271,7 +270,7 @@ impl PropertyParser {
 	/// properties.insert("width".to_string(),
 	/// 	Property::new(true, "Width of the element in em".to_string(), None));
 	///
-	/// let parser = PropertyParser::new(properties);
+	/// let parser = PropertyParser { properties };
 	/// let pm = parser.parse("width=15").unwrap();
 	///
 	/// assert_eq!(pm.get("width", |_, s| s.parse::<i32>()).unwrap().1, 15);
@@ -491,7 +490,7 @@ mod tests {
 			Property::new(false, "Weight in %".to_string(), Some("0.42".to_string())),
 		);
 
-		let parser = PropertyParser::new(properties);
+		let parser = PropertyParser { properties };
 		let pm = parser.parse("width=15,length=-10").unwrap();
 
 		// Ok