Repository: Textualize/textual
Pull request: Review styles reference
**Please review the following checklist.**

- [x] Updated documentation – well, that _is_ the point of this PR :D
- [ ] Updated CHANGELOG.md (where appropriate)


Problem statement:
Review Styles Reference
Some CSS rules have missing values documented. We should review all the CSS rules un the reference section of the docs, to add anything missing.

Document CSS units
We need to document Textual CSS units (%, vw, fr etc).

Where do we put them? I have a feeling this should go in the guide in a section under CSS, but also in the Reference section with more detail.

Hints from issue discussion:
Pages in the reference and status tracker:

 - [x] align (added an example with a complete alignment grid)
 - [x] background (added example with different transparencies; improved `Color` documentation to make it clearer what color formats are accepted; added a couple more examples to the CSS and Python ways of changing the background)
 - [x] border (add description of how multiple rules affecting the same edge resolve [most recent rule wins]; add example with all borders in a single app; added paragraph about available colors; added paragraph about default border when color is set and default color when border is set)
 - [x] box-sizing
 - [x] color (add paragraph about available colours; add app that shows how `auto` picks a color with good contrast for readability)
 - [x] content-align (add syntax for `content-align-horizontal` and `content-align-vertical`; cross-reference `align` and `content-align`; add example app with all 9 alignment examples;)
 - [x] display
 - [x] dock
 - [x] grid (created subpages for the grid-related styles; added example apps to each one of those)
 - [x] height (added example showing all types of height units)
 - [x] layer (fixed syntax to programmatically change `layer` in Python; linked to `layers`)
 - [x] layers (fixed syntax to programmatically change `layers` in Python; linked to `layer`)
 - [x] layout (uniformise how options are listed in the syntax; add link to grid reference; fix Python syntax to change layout programmatically)
 - [x] links (add examples for all link rules; record videos showing the hover styles and add as GIFs; mention the default behavior for hover background; leave TO DO questions at the bottom)
 - [x] margin (add example for all margins)
 - [x] max-height (add example and refactor reference)
 - [x] max-width (add example and refactor reference)
 - [x] min-height (add example and refactor reference)
 - [x] min-width (add example and refactor reference)
 - [x] offset (change example to use negative offset; refactor to use new syntax, types, and template)
 - [ ] opacity
 - [ ] outline
 - [ ] overflow
 - [ ] padding
 - [ ] scrollbar colors
 - [ ] scrollbar-gutter
 - [ ] scrollbar-size
 - [ ] text-align
 - [ ] text-style
 - [ ] text-opacity
 - [ ] tint
 - [ ] visibility
 - [ ] width

Other changes:
 - Created a reusable short markdown file `docs/styles/snippets/color_css_syntax.md` with a paragraph about the legal values for colors in Textual CSS. This snippet is reused throughout the docs.
 - Ended up doing the same for several units.
 - W.r.t. #1344, created a folder under "Reference / Styles" that documents CSS units (see issue for more details).
 - Split pages with multiple rules into a main reference (the page that already existed) and then subpages for the individual rules:
    - Grid
    - Links
    - Scrollbar colors

## To do

 - Should text style aliases be documented?
 - Textual suggests that `not`, `blink`, and `overline` are valid text styles. Are they?
@willmcgugan @rodrigogiraoserrao can this be labeled as `good first issue` there seems to be no issues with that label
This is currently being worked on by @rodrigogiraoserrao. 
@davep Yea OK I see that he was assigned, I am just wondering are there any issues in the backlog that can be labeled as `good first issue`?
[There doesn't appear to be](https://github.com/Textualize/textual/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22+no%3Aassignee). Perhaps, rather than ping folk involved and tracking this issue, it might make more sense to ask about something that general in [the discussions](https://github.com/Textualize/textual/discussions) or on the [Discord Server](https://discord.gg/Enf6Z3qhVr).
Great, thanks didn't know about the Discord Server.
Sorry for not replying during the weekend, @WMRamadan.
To be honest, this wouldn't even be a great first issue because there are some docs layout decisions to be made here, etc. But thanks for your enthusiasm!

In any case, following @davep's suggestions seems the way to go.

Commit message: Replace statics with labels.

[skip ci]

Patch to review:
diff --git a/docs/css_types/_template.md b/docs/css_types/_template.md
new file mode 100644
index 0000000000..c9fe058d42
--- /dev/null
+++ b/docs/css_types/_template.md
@@ -0,0 +1,40 @@
+<!-- Template file for a Textual CSS type reference page. -->
+
+# &lt;type-name&gt;
+
+<!-- Short description of the type. -->
+
+## Syntax
+
+<!--
+--8<-- "docs/snippets/type_syntax/type_name.md"
+-->
+
+## Examples
+
+### CSS
+
+<!--
+Examples should be rule-agnostic.
+Include a good variety of examples.
+If the type has many different syntaxes, cover all of them.
+Add comments when needed/if helpful.
+-->
+
+```sass
+* {
+    rule: type-value-1;
+    rule: type-value-2;
+    rule: type-value-3;
+}
+```
+
+### Python
+
+<!-- Same examples as above. -->
+
+```py
+type_name = type_value_1
+type_name = type_value_2
+type_name = type_value_3
+```
diff --git a/docs/css_types/border.md b/docs/css_types/border.md
new file mode 100644
index 0000000000..eb37d685c8
--- /dev/null
+++ b/docs/css_types/border.md
@@ -0,0 +1,59 @@
+# &lt;border&gt;
+
+The `<border>` CSS type represents a border style.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/border.md"
+
+## Border command
+
+The `textual` CLI has a subcommand which will let you explore the various border types interactively, when applied to the CSS rule [`border`](../styles/border.md):
+
+```
+textual borders
+```
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: ascii   /* A border with plus, hyphen, and vertical bar characters. */
+    rule: blank   /* A blank border (reserves space for a border). */
+    rule: dashed  /* Dashed line border. */
+    rule: double  /* Double lined border. */
+    rule: heavy   /* Heavy border. */
+    rule: hidden  /* Alias for "none". */
+    rule: hkey    /* Horizontal key-line border. */
+    rule: inner   /* Thick solid border. */
+    rule: none    /* Disabled border. */
+    rule: outer   /* Solid border with additional space around content. */
+    rule: round   /* Rounded corners. */
+    rule: solid   /* Solid border. */
+    rule: tall    /* Solid border with additional space top and bottom. */
+    rule: vkey    /* Vertical key-line border. */
+    rule: wide    /* Solid border with additional space left and right. */
+}
+```
+
+### Python
+
+```py
+border = "ascii"   # A border with plus, hyphen, and vertical bar characters.
+border = "blank"   # A blank border (reserves space for a border).
+border = "dashed"  # Dashed line border.
+border = "double"  # Double lined border.
+border = "heavy"   # Heavy border.
+border = "hidden"  # Alias for "none".
+border = "hkey"    # Horizontal key-line border.
+border = "inner"   # Thick solid border.
+border = "none"    # Disabled border.
+border = "outer"   # Solid border with additional space around content.
+border = "round"   # Rounded corners.
+border = "solid"   # Solid border.
+border = "tall"    # Solid border with extras space top and bottom.
+border = "vkey"    # Vertical key-line border.
+border = "wide"    # Solid border with additional space left and right.
+```
diff --git a/docs/css_types/color.md b/docs/css_types/color.md
new file mode 100644
index 0000000000..db3e82b966
--- /dev/null
+++ b/docs/css_types/color.md
@@ -0,0 +1,43 @@
+# &lt;color&gt;
+
+The `<color>` CSS type represents a color.
+
+!!! warning
+
+    Not to be confused with the [`color`](../styles/color.md) CSS rule to set text color.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: red;               /* color name                     */
+    rule: #A8F;              /* 3-digit hex RGB                */
+    rule: #FF00FFDD;         /* 6-digit hex RGB + transparency */
+    rule: rgb(15,200,73);    /* RGB description                */
+    rule: hsl(300,20%,70%);  /* HSL description                */
+    rule: $accent;           /* Textual variable               */
+}
+```
+
+### Python
+
+```py
+# Mimicking the CSS syntax
+color = "red"
+color = "#A8F"
+color = "#FF00FFDD"
+color = "rgb(15,200,73)"
+color = "hsl(300,20%,70%)"
+color = "$accent"
+
+# Using a Color object directly...
+color = Color(16, 200, 45)
+# ... which can also parse the CSS syntax
+color = Color.parse("#A8F")
+```
diff --git a/docs/css_types/horizontal.md b/docs/css_types/horizontal.md
new file mode 100644
index 0000000000..2aef91b473
--- /dev/null
+++ b/docs/css_types/horizontal.md
@@ -0,0 +1,27 @@
+# &lt;horizontal&gt;
+
+The `<horizontal>` CSS type represents a position along the horizontal axis.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/horizontal.md"
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: left;
+    rule: center;
+    rule: right
+}
+```
+
+### Python
+
+```py
+horizontal = "left"
+horizontal = "center"
+horizontal = "right"
+```
diff --git a/docs/css_types/index.md b/docs/css_types/index.md
new file mode 100644
index 0000000000..7f48be2def
--- /dev/null
+++ b/docs/css_types/index.md
@@ -0,0 +1,12 @@
+# CSS Types
+
+CSS types define the values that Textual CSS styles accept.
+
+CSS types will be linked from within the [styles reference](../styles/index.md) in the "Formal Syntax" section of each style.
+The CSS types will be denoted by a keyword enclosed by angle brackets `<` and `>`.
+
+For example, the style [`align-horizontal`](../styles/align.md) references the CSS type [`<horizontal>`](./horizontal.md):
+
+--8<-- "docs/snippets/syntax_block_start.md"
+align-horizontal: <a href="./horizontal.md">&lt;horizontal&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
diff --git a/docs/css_types/integer.md b/docs/css_types/integer.md
new file mode 100644
index 0000000000..cde2faa1a4
--- /dev/null
+++ b/docs/css_types/integer.md
@@ -0,0 +1,31 @@
+# &lt;integer&gt;
+
+The `<integer>` CSS type represents an integer number.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/integer.md"
+
+!!! note
+
+    Some CSS rules may expect an `<integer>` within certain bounds. If that is the case, it will be noted in that rule.
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: -5;
+    rule: 10;
+}
+```
+
+### Python
+
+In Python, a rule that expects a CSS type `<integer>` will expect a value of the type `int`:
+
+```py
+integer = -5
+integer = 10
+```
diff --git a/docs/css_types/name.md b/docs/css_types/name.md
new file mode 100644
index 0000000000..00998e2c00
--- /dev/null
+++ b/docs/css_types/name.md
@@ -0,0 +1,33 @@
+# &lt;name&gt;
+
+The `<name>` type represents a sequence of characters that identifies something.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/name.md"
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: onlyLetters;
+    rule: Letters-and-hiphens;
+    rule: _leading-underscore;
+    rule: letters-and-1-digit;
+    rule: name1234567890;
+}
+```
+
+### Python
+
+<!-- Same examples as above. -->
+
+```py
+name = "onlyLetters"
+name = "Letters-and-hiphens"
+name = "_leading-underscore"
+name = "letters-and-1-digit"
+name = "name1234567890"
+```
diff --git a/docs/css_types/number.md b/docs/css_types/number.md
new file mode 100644
index 0000000000..0e1cc3e8f5
--- /dev/null
+++ b/docs/css_types/number.md
@@ -0,0 +1,31 @@
+# &lt;number&gt;
+
+The `<number>` CSS type represents a real number, which can be an integer or a number with a decimal part (akin to a `float` in Python).
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/number.md"
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    css-rule: 6       /* Integers are numbers */
+    css-rule: -13     /* Numbers can be negative */
+    css-rule: 4.75    /* Numbers can have a decimal part */
+    css-rule: -73.73
+}
+```
+
+### Python
+
+In Python, a rule that expects a CSS type `<number>` will accept an `int` or a `float`:
+
+```py
+number = 6       # ints are numbers
+number = -13     # ints can be negative
+number = 4.75    # floats are numbers
+number = -73.73  # negative floats too
+```
diff --git a/docs/css_types/overflow.md b/docs/css_types/overflow.md
new file mode 100644
index 0000000000..c5fe6010ef
--- /dev/null
+++ b/docs/css_types/overflow.md
@@ -0,0 +1,27 @@
+# &lt;overflow&gt;
+
+The `<overflow>` CSS type represents overflow modes.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/overflow.md"
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: auto;    /* Determine overflow mode automatically. */
+    rule: hidden;  /* Don't overflow. */
+    rule: scroll;  /* Allow overflowing. */
+}
+```
+
+### Python
+
+```py
+overflow = "auto"    # Determine overflow mode automatically.
+overflow = "hidden"  # Don't overflow.
+overflow = "scroll"  # Allow overflowing.
+```
diff --git a/docs/css_types/percentage.md b/docs/css_types/percentage.md
new file mode 100644
index 0000000000..c7196bd94d
--- /dev/null
+++ b/docs/css_types/percentage.md
@@ -0,0 +1,30 @@
+# &lt;percentage&gt;
+
+The `<percentage>` CSS type represents a percentage value.
+It is often used to represent values that are relative to the parent's values.
+
+!!! warning
+
+    Not to be confused with the [`<scalar>`](./scalar.md) type.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+Some rules may clamp the values between `0%` and `100%`.
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: 70%;    /* Integer followed by % */
+    rule: -3.5%;  /* The number can be negative/decimal */
+}
+```
+
+### Python
+
+```py
+percentage = "70%"
+```
diff --git a/docs/css_types/scalar.md b/docs/css_types/scalar.md
new file mode 100644
index 0000000000..7e37e7fca2
--- /dev/null
+++ b/docs/css_types/scalar.md
@@ -0,0 +1,116 @@
+# &lt;scalar&gt;
+
+The `<scalar>` CSS type represents a length.
+It can be a [`<number>`](./number.md) and a unit, or the special value `auto`.
+It is used to represent lengths, for example in the [`width`](../styles/width.md) and [`height`](../styles/height.md) rules.
+
+!!! warning
+
+    Not to be confused with the [`<number>`](./number.md) or [`<percentage>`](./percentage.md) types.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
+
+A complete reference table and detailed explanations follow.
+You can [skip to the examples](#examples).
+
+| Unit symbol | Unit            | Example | Description                                                 |
+|-------------|-----------------|---------|-------------------------------------------------------------|
+| `""`        | Cell            | `10`    | Number of cells (rows or columns).                          |
+| `"fr"`      | Fraction        | `1fr`   | Specifies the proportion of space the widget should occupy. |
+| `"%"`       | Percent         | `75%`   | Length relative to the container widget.                    |
+| `"w"`       | Width           | `25w`   | Percentage relative to the width of the container widget.   |
+| `"h"`       | Height          | `75h`   | Percentage relative to the height of the container widget.  |
+| `"vw"`      | Viewport width  | `25vw`  | Percentage relative to the viewport width.                  |
+| `"vh"`      | Viewport height | `75vh`  | Percentage relative to the viewport height.                 |
+| -           | Auto            | `auto`  | Tries to compute the optimal size to fit without scrolling. |
+
+### Cell
+
+The number of cells is the only unit for a scalar that is _absolute_.
+This can be an integer or a float but floats are truncated to integers.
+
+If used to specify a horizontal length, it corresponds to the number of columns.
+For example, in `width: 15`, this sets the width of a widget to be equal to 15 cells, which translates to 15 columns.
+
+If used to specify a vertical length, it corresponds to the number of lines.
+For example, in `height: 10`, this sets the height of a widget to be equal to 10 cells, which translates to 10 lines.
+
+### Fraction
+
+The unit fraction is used to represent proportional sizes.
+
+For example, if two widgets are side by side and one has `width: 1fr` and the other has `width: 3fr`, the second one will be three times as wide as the first one.
+
+### Percent
+
+The percent unit matches a [`<percentage>`](./percentage.md) and is used to specify a total length relative to the space made available by the container widget.
+
+If used to specify a horizontal length, it will be relative to the width of the container.
+For example, `width: 50%` sets the width of a widget to 50% of the width of its container.
+
+If used to specify a vertical length, it will be relative to the height of the container.
+For example, `height: 50%` sets the height of a widget to 50% of the height of its container.
+
+### Width
+
+The width unit is similar to the percent unit, except it sets the percentage to be relative to the width of the container.
+
+For example, `width: 25w` sets the width of a widget to 25% of the width of its container and `height: 25w` sets the height of a widget to 25% of the width of its container.
+So, if the container has a width of 100 cells, the width and the height of the child widget will be of 25 cells.
+
+### Height
+
+The height unit is similar to the percent unit, except it sets the percentage to be relative to the height of the container.
+
+For example, `height: 75h` sets the height of a widget to 75% of the height of its container and `width: 75h` sets the width of a widget to 75% of the height of its container.
+So, if the container has a height of 100 cells, the width and the height of the child widget will be of 75 cells.
+
+### Viewport width
+
+This is the same as the [width unit](#width), except that it is relative to the width of the viewport instead of the width of the immediate container.
+
+For example, `width: 25vw` will try to set the width of a widget to be 25% of the viewport width, regardless of the widths of its containers.
+
+### Viewport height
+
+This is the same as the [height unit](#height), except that it is relative to the height of the viewport instead of the height of the immediate container.
+
+For example, `height: 75vh` will try to set the height of a widget to be 75% of the viewport height, regardless of the height of its containers.
+
+### Auto
+
+This special value will try to calculate the optimal size to fit the contents of the widget without scrolling.
+
+For example, if its container is big enough, a label with `width: auto` will be just as wide as its text.
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: 16;    /* 16 cells */
+    rule: 1fr;   /* proportional size of 1 */
+    rule: 50%;   /* 50% of the same dimension of the parent */
+    rule: 25w;   /* 25% of the width of the parent */
+    rule: 75h;   /* 75% of the height of the parent */
+    rule: 25vw;  /* 25% of the viewport width */
+    rule: 75vh;  /* 75% of the viewport height */
+    rule: auto;  /* special value */
+}
+```
+
+### Python
+
+```py
+scalar = 16      # Cell unit can be specified with an int/float
+scalar = "1fr"   # proportional size of 1
+scalar = "50%"   # 50% of the same dimension of the parent
+scalar = "25w"   # 25% of the width of the parent
+scalar = "75h"   # 75% of the height of the parent
+scalar = "25vw"  # 25% of the viewport width
+scalar = "75vh"  # 75% of the viewport height
+scalar = "auto"  # special value
+```
diff --git a/docs/css_types/text_align.md b/docs/css_types/text_align.md
new file mode 100644
index 0000000000..c9fc597859
--- /dev/null
+++ b/docs/css_types/text_align.md
@@ -0,0 +1,37 @@
+# &lt;text-align&gt;
+
+The `<text-align>` CSS type represents alignments that can be applied to text.
+
+!!! warning
+
+    Not to be confused with the [`text-align`](../styles/text_align.md) CSS rule that sets the alignment of text in a widget.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/text_align.md"
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: center;
+    rule: end;
+    rule: justify;
+    rule: left;
+    rule: right;
+    rule: start;
+}
+```
+
+### Python
+
+```py
+text_align = "center"
+text_align = "end"
+text_align = "justify"
+text_align = "left"
+text_align = "right"
+text_align = "start"
+```
diff --git a/docs/css_types/text_style.md b/docs/css_types/text_style.md
new file mode 100644
index 0000000000..5f128b0043
--- /dev/null
+++ b/docs/css_types/text_style.md
@@ -0,0 +1,47 @@
+# &lt;text-style&gt;
+
+The `<text-style>` CSS type represents styles that can be applied to text.
+
+!!! warning
+
+    Not to be confused with the [`text-style`](../styles/text_style.md) CSS rule that sets the style of text in a widget.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/text_style.md"
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    /* You can specify any value by itself. */
+    rule: bold;
+    rule: italic;
+    rule: none;
+    rule: reverse;
+    rule: strike;
+    rule: underline;
+
+    /* You can also combine multiple values. */
+    rule: strike bold italic reverse;
+    rule: bold underline italic;
+}
+```
+
+### Python
+
+```py
+# You can specify any value by itself
+text_style = "bold"
+text_style = "italic"
+text_style = "none"
+text_style = "reverse"
+text_style = "strike"
+text_style = "underline"
+
+# You can also combine multiple values
+text_style = "strike bold italic reverse"
+text_style = "bold underline italic"
+```
diff --git a/docs/css_types/vertical.md b/docs/css_types/vertical.md
new file mode 100644
index 0000000000..f301e1fe10
--- /dev/null
+++ b/docs/css_types/vertical.md
@@ -0,0 +1,27 @@
+# &lt;vertical&gt;
+
+The `<vertical>` CSS type represents a position along the vertical axis.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/vertical.md"
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: top;
+    rule: middle;
+    rule: bottom
+}
+```
+
+### Python
+
+```py
+vertical = "top"
+vertical = "middle"
+vertical = "bottom"
+```
diff --git a/docs/examples/guide/layout/layers.css b/docs/examples/guide/layout/layers.css
index 4465b2d91c..7dab8dfd5f 100644
--- a/docs/examples/guide/layout/layers.css
+++ b/docs/examples/guide/layout/layers.css
@@ -11,8 +11,8 @@ Static {
 }
 
 #box1 {
-    background: darkcyan;
     layer: above;
+    background: darkcyan;
 }
 
 #box2 {
diff --git a/docs/examples/styles/align.py b/docs/examples/styles/align.py
index 6abee37ce4..89f293aae5 100644
--- a/docs/examples/styles/align.py
+++ b/docs/examples/styles/align.py
@@ -1,11 +1,11 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 
 class AlignApp(App):
     def compose(self):
-        yield Static("Vertical alignment with [b]Textual[/]", classes="box")
-        yield Static("Take note, browsers.", classes="box")
+        yield Label("Vertical alignment with [b]Textual[/]", classes="box")
+        yield Label("Take note, browsers.", classes="box")
 
 
 app = AlignApp(css_path="align.css")
diff --git a/docs/examples/styles/align_all.css b/docs/examples/styles/align_all.css
new file mode 100644
index 0000000000..6f3aa58e37
--- /dev/null
+++ b/docs/examples/styles/align_all.css
@@ -0,0 +1,53 @@
+#left-top {
+    /* align: left top; this is the default value and is implied. */
+}
+
+#center-top {
+    align: center top;
+}
+
+#right-top {
+    align: right top;
+}
+
+#left-middle {
+    align: left middle;
+}
+
+#center-middle {
+    align: center middle;
+}
+
+#right-middle {
+    align: right middle;
+}
+
+#left-bottom {
+    align: left bottom;
+}
+
+#center-bottom {
+    align: center bottom;
+}
+
+#right-bottom {
+    align: right bottom;
+}
+
+Screen {
+    layout: grid;
+    grid-size: 3 3;
+    grid-gutter: 1;
+}
+
+Container {
+    background: $boost;
+    border: solid gray;
+    height: 100%;
+}
+
+Label {
+    width: auto;
+    height: 1;
+    background: $accent;
+}
diff --git a/docs/examples/styles/align_all.py b/docs/examples/styles/align_all.py
new file mode 100644
index 0000000000..1ff8d6040c
--- /dev/null
+++ b/docs/examples/styles/align_all.py
@@ -0,0 +1,20 @@
+from textual.app import App, ComposeResult
+from textual.containers import Container
+from textual.widgets import Label
+
+
+class AlignAllApp(App):
+    """App that illustrates all alignments."""
+
+    CSS_PATH = "align_all.css"
+
+    def compose(self) -> ComposeResult:
+        yield Container(Label("left top"), id="left-top")
+        yield Container(Label("center top"), id="center-top")
+        yield Container(Label("right top"), id="right-top")
+        yield Container(Label("left middle"), id="left-middle")
+        yield Container(Label("center middle"), id="center-middle")
+        yield Container(Label("right middle"), id="right-middle")
+        yield Container(Label("left bottom"), id="left-bottom")
+        yield Container(Label("center bottom"), id="center-bottom")
+        yield Container(Label("right bottom"), id="right-bottom")
diff --git a/docs/examples/styles/background_transparency.css b/docs/examples/styles/background_transparency.css
new file mode 100644
index 0000000000..9c38d28881
--- /dev/null
+++ b/docs/examples/styles/background_transparency.css
@@ -0,0 +1,49 @@
+#t10 {
+    background: red 10%;
+}
+
+#t20 {
+    background: red 20%;
+}
+
+#t30 {
+    background: red 30%;
+}
+
+#t40 {
+    background: red 40%;
+}
+
+#t50 {
+    background: red 50%;
+}
+
+#t60 {
+    background: red 60%;
+}
+
+#t70 {
+    background: red 70%;
+}
+
+#t80 {
+    background: red 80%;
+}
+
+#t90 {
+    background: red 90%;
+}
+
+#t100 {
+    background: red 100%;
+}
+
+Screen {
+    layout: horizontal;
+}
+
+Static {
+    height: 100%;
+    width: 1fr;
+    content-align: center middle;
+}
diff --git a/docs/examples/styles/background_transparency.py b/docs/examples/styles/background_transparency.py
new file mode 100644
index 0000000000..942bb51b8a
--- /dev/null
+++ b/docs/examples/styles/background_transparency.py
@@ -0,0 +1,20 @@
+from textual.app import App, ComposeResult
+from textual.widgets import Static
+
+
+class BackgroundTransparencyApp(App):
+    """Simple app to exemplify different transparency settings."""
+    def compose(self) -> ComposeResult:
+        yield Static("10%", id="t10")
+        yield Static("20%", id="t20")
+        yield Static("30%", id="t30")
+        yield Static("40%", id="t40")
+        yield Static("50%", id="t50")
+        yield Static("60%", id="t60")
+        yield Static("70%", id="t70")
+        yield Static("80%", id="t80")
+        yield Static("90%", id="t90")
+        yield Static("100%", id="t100")
+
+
+app = BackgroundTransparencyApp(css_path="background_transparency.css")
diff --git a/docs/examples/styles/border.css b/docs/examples/styles/border.css
index 762430dc82..27b9e281df 100644
--- a/docs/examples/styles/border.css
+++ b/docs/examples/styles/border.css
@@ -1,24 +1,25 @@
 Screen {
     background: white;
 }
-Screen > Static {
+Screen > Label {
+    width: 100%;
     height: 5;
     content-align: center middle;
     color: white;
     margin: 1;
     box-sizing: border-box;
 }    
-#static1 {
+#label1 {
     background: red 20%;
     color: red;
     border: solid red;
 }
-#static2 {
+#label2 {
     background: green 20%;
     color: green;
     border: dashed green;
 }
-#static3 {
+#label3 {
     background: blue 20%;
     color: blue;
     border: tall blue;
diff --git a/docs/examples/styles/border.py b/docs/examples/styles/border.py
index 4dbc8ef4fb..d426e85b0d 100644
--- a/docs/examples/styles/border.py
+++ b/docs/examples/styles/border.py
@@ -1,12 +1,12 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 
 class BorderApp(App):
     def compose(self):
-        yield Static("My border is solid red", id="static1")
-        yield Static("My border is dashed green", id="static2")
-        yield Static("My border is tall blue", id="static3")
+        yield Label("My border is solid red", id="label1")
+        yield Label("My border is dashed green", id="label2")
+        yield Label("My border is tall blue", id="label3")
 
 
 app = BorderApp(css_path="border.css")
diff --git a/docs/examples/styles/border_all.css b/docs/examples/styles/border_all.css
new file mode 100644
index 0000000000..527b1adab3
--- /dev/null
+++ b/docs/examples/styles/border_all.css
@@ -0,0 +1,71 @@
+#ascii {
+    border: ascii $accent;
+}
+
+#blank {
+    border: blank $accent;
+}
+
+#dashed {
+    border: dashed $accent;
+}
+
+#double {
+    border: double $accent;
+}
+
+#heavy {
+    border: heavy $accent;
+}
+
+#hidden {
+    border: hidden $accent;
+}
+
+#hkey {
+    border: hkey $accent;
+}
+
+#inner {
+    border: inner $accent;
+}
+
+#none {
+    border: none $accent;
+}
+
+#outer {
+    border: outer $accent;
+}
+
+#round {
+    border: round $accent;
+}
+
+#solid {
+    border: solid $accent;
+}
+
+#tall {
+    border: tall $accent;
+}
+
+#vkey {
+    border: vkey $accent;
+}
+
+#wide {
+    border: wide $accent;
+}
+
+Grid {
+    grid-size: 3 5;
+    align: center middle;
+    grid-gutter: 1 2;
+}
+
+Label {
+    width: 20;
+    height: 3;
+    content-align: center middle;
+}
diff --git a/docs/examples/styles/border_all.py b/docs/examples/styles/border_all.py
new file mode 100644
index 0000000000..d839c3e5af
--- /dev/null
+++ b/docs/examples/styles/border_all.py
@@ -0,0 +1,26 @@
+from textual.app import App
+from textual.containers import Grid
+from textual.widgets import Label
+
+
+class AllBordersApp(App):
+    def compose(self):
+        yield Grid(
+            Label("ascii", id="ascii"),
+            Label("blank", id="blank"),
+            Label("dashed", id="dashed"),
+            Label("double", id="double"),
+            Label("heavy", id="heavy"),
+            Label("hidden/none", id="hidden"),
+            Label("hkey", id="hkey"),
+            Label("inner", id="inner"),
+            Label("none", id="none"),
+            Label("outer", id="outer"),
+            Label("round", id="round"),
+            Label("solid", id="solid"),
+            Label("tall", id="tall"),
+            Label("vkey", id="vkey"),
+            Label("wide", id="wide"),
+        )
+
+app = AllBordersApp(css_path="border_all.css")
diff --git a/docs/examples/styles/color.css b/docs/examples/styles/color.css
index b5552495ae..b44a0d02e7 100644
--- a/docs/examples/styles/color.css
+++ b/docs/examples/styles/color.css
@@ -1,13 +1,14 @@
-Static {
+Label {
     height:1fr;
     content-align: center middle;
+    width: 100%;
 }    
-#static1 {
+#label1 {
     color: red;
 }
-#static2 {
+#label2 {
     color: rgb(0, 255, 0);
 }
-#static3 {
+#label3 {
     color: hsl(240, 100%, 50%)
 }
diff --git a/docs/examples/styles/color.py b/docs/examples/styles/color.py
index 26543b0a04..0f10ea39ed 100644
--- a/docs/examples/styles/color.py
+++ b/docs/examples/styles/color.py
@@ -1,12 +1,12 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 
 class ColorApp(App):
     def compose(self):
-        yield Static("I'm red!", id="static1")
-        yield Static("I'm rgb(0, 255, 0)!", id="static2")
-        yield Static("I'm hsl(240, 100%, 50%)!", id="static3")
+        yield Label("I'm red!", id="label1")
+        yield Label("I'm rgb(0, 255, 0)!", id="label2")
+        yield Label("I'm hsl(240, 100%, 50%)!", id="label3")
 
 
 app = ColorApp(css_path="color.css")
diff --git a/docs/examples/styles/color_auto.css b/docs/examples/styles/color_auto.css
new file mode 100644
index 0000000000..08fab1d0f3
--- /dev/null
+++ b/docs/examples/styles/color_auto.css
@@ -0,0 +1,26 @@
+Label {
+    color: auto 80%;
+    content-align: center middle;
+    height: 1fr;
+    width: 100%;
+}
+
+#lbl1 {
+    background: red 80%;
+}
+
+#lbl2 {
+    background: yellow 80%;
+}
+
+#lbl3 {
+    background: blue 80%;
+}
+
+#lbl4 {
+    background: pink 80%;
+}
+
+#lbl5 {
+    background: green 80%;
+}
diff --git a/docs/examples/styles/color_auto.py b/docs/examples/styles/color_auto.py
new file mode 100644
index 0000000000..5202415c52
--- /dev/null
+++ b/docs/examples/styles/color_auto.py
@@ -0,0 +1,14 @@
+from textual.app import App
+from textual.widgets import Label
+
+
+class ColorApp(App):
+    def compose(self):
+        yield Label("The quick brown fox jumps over the lazy dog!", id="lbl1")
+        yield Label("The quick brown fox jumps over the lazy dog!", id="lbl2")
+        yield Label("The quick brown fox jumps over the lazy dog!", id="lbl3")
+        yield Label("The quick brown fox jumps over the lazy dog!", id="lbl4")
+        yield Label("The quick brown fox jumps over the lazy dog!", id="lbl5")
+
+
+app = ColorApp(css_path="color_auto.css")
diff --git a/docs/examples/styles/column_span.css b/docs/examples/styles/column_span.css
new file mode 100644
index 0000000000..d96fbf4f38
--- /dev/null
+++ b/docs/examples/styles/column_span.css
@@ -0,0 +1,30 @@
+#p1 {
+    column-span: 4;
+}
+#p2 {
+    column-span: 3;
+}
+#p3 {
+    column-span: 1;  /* Didn't need to be set explicitly. */
+}
+#p4 {
+    column-span: 2;
+}
+#p5 {
+    column-span: 2;
+}
+#p6 {
+    /* Default value is 1. */
+}
+#p7 {
+    column-span: 3;
+}
+
+Grid {
+    grid-size: 4 4;
+    grid-gutter: 1 2;
+}
+
+Placeholder {
+    height: 100%;
+}
diff --git a/docs/examples/styles/column_span.py b/docs/examples/styles/column_span.py
new file mode 100644
index 0000000000..272819621a
--- /dev/null
+++ b/docs/examples/styles/column_span.py
@@ -0,0 +1,19 @@
+from textual.app import App
+from textual.containers import Grid
+from textual.widgets import Placeholder
+
+
+class MyApp(App):
+    def compose(self):
+        yield Grid(
+            Placeholder(id="p1"),
+            Placeholder(id="p2"),
+            Placeholder(id="p3"),
+            Placeholder(id="p4"),
+            Placeholder(id="p5"),
+            Placeholder(id="p6"),
+            Placeholder(id="p7"),
+        )
+
+
+app = MyApp(css_path="column_span.css")
diff --git a/docs/examples/styles/content_align.css b/docs/examples/styles/content_align.css
index 7024809b09..c195a9fffa 100644
--- a/docs/examples/styles/content_align.css
+++ b/docs/examples/styles/content_align.css
@@ -4,7 +4,8 @@
 }
 
 #box2 {
-    content-align: center middle;
+    content-align-horizontal: center;
+    content-align-vertical: middle;
     background: green;
 }
 
@@ -13,7 +14,8 @@
     background: blue;
 }
 
-Static {
+Label {
+    width: 100%;
     height: 1fr;
     padding: 1;
     color: white;
diff --git a/docs/examples/styles/content_align.py b/docs/examples/styles/content_align.py
index c0213c63e7..25bb3b29c5 100644
--- a/docs/examples/styles/content_align.py
+++ b/docs/examples/styles/content_align.py
@@ -1,12 +1,12 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 
 class ContentAlignApp(App):
     def compose(self):
-        yield Static("With [i]content-align[/] you can...", id="box1")
-        yield Static("...[b]Easily align content[/]...", id="box2")
-        yield Static("...Horizontally [i]and[/] vertically!", id="box3")
+        yield Label("With [i]content-align[/] you can...", id="box1")
+        yield Label("...[b]Easily align content[/]...", id="box2")
+        yield Label("...Horizontally [i]and[/] vertically!", id="box3")
 
 
 app = ContentAlignApp(css_path="content_align.css")
diff --git a/docs/examples/styles/content_align_all.css b/docs/examples/styles/content_align_all.css
new file mode 100644
index 0000000000..1d1e099a39
--- /dev/null
+++ b/docs/examples/styles/content_align_all.css
@@ -0,0 +1,39 @@
+#left-top {
+    /* content-align: left top; this is the default implied value. */
+}
+#center-top {
+    content-align: center top;
+}
+#right-top {
+    content-align: right top;
+}
+#left-middle {
+    content-align: left middle;
+}
+#center-middle {
+    content-align: center middle;
+}
+#right-middle {
+    content-align: right middle;
+}
+#left-bottom {
+    content-align: left bottom;
+}
+#center-bottom {
+    content-align: center bottom;
+}
+#right-bottom {
+    content-align: right bottom;
+}
+
+Screen {
+    layout: grid;
+    grid-size: 3 3;
+    grid-gutter: 1;
+}
+
+Label {
+    width: 100%;
+    height: 100%;
+    background: $primary;
+}
diff --git a/docs/examples/styles/content_align_all.py b/docs/examples/styles/content_align_all.py
new file mode 100644
index 0000000000..0460116672
--- /dev/null
+++ b/docs/examples/styles/content_align_all.py
@@ -0,0 +1,18 @@
+from textual.app import App
+from textual.widgets import Label
+
+
+class AllContentAlignApp(App):
+    def compose(self):
+        yield Label("left top", id="left-top")
+        yield Label("center top", id="center-top")
+        yield Label("right top", id="right-top")
+        yield Label("left middle", id="left-middle")
+        yield Label("center middle", id="center-middle")
+        yield Label("right middle", id="right-middle")
+        yield Label("left bottom", id="left-bottom")
+        yield Label("center bottom", id="center-bottom")
+        yield Label("right bottom", id="right-bottom")
+
+
+app = AllContentAlignApp(css_path="content_align_all.css")
diff --git a/docs/examples/styles/dock_all.css b/docs/examples/styles/dock_all.css
new file mode 100644
index 0000000000..2a78c8616b
--- /dev/null
+++ b/docs/examples/styles/dock_all.css
@@ -0,0 +1,34 @@
+#left {
+    dock: left;
+    height: 100%;
+    width: auto;
+    align-vertical: middle;
+}
+#top {
+    dock: top;
+    height: auto;
+    width: 100%;
+    align-horizontal: center;
+}
+#right {
+    dock: right;
+    height: 100%;
+    width: auto;
+    align-vertical: middle;
+}
+#bottom {
+    dock: bottom;
+    height: auto;
+    width: 100%;
+    align-horizontal: center;
+}
+
+Screen {
+    align: center middle;
+}
+
+#big_container {
+    width: 75%;
+    height: 75%;
+    border: round white;
+}
diff --git a/docs/examples/styles/dock_all.py b/docs/examples/styles/dock_all.py
new file mode 100644
index 0000000000..30907f98a8
--- /dev/null
+++ b/docs/examples/styles/dock_all.py
@@ -0,0 +1,17 @@
+from textual.app import App
+from textual.containers import Container
+from textual.widgets import Label
+
+
+class DockAllApp(App):
+    def compose(self):
+        yield Container(
+            Container(Label("left"), id="left"),
+            Container(Label("top"), id="top"),
+            Container(Label("right"), id="right"),
+            Container(Label("bottom"), id="bottom"),
+            id="big_container",
+        )
+
+
+app = DockAllApp(css_path="dock_all.css")
diff --git a/docs/examples/styles/grid_columns.css b/docs/examples/styles/grid_columns.css
new file mode 100644
index 0000000000..dc3aa47db4
--- /dev/null
+++ b/docs/examples/styles/grid_columns.css
@@ -0,0 +1,11 @@
+Grid {
+    grid-size: 5 2;
+    grid-columns: 1fr 16 2fr;
+}
+
+Label {
+    border: round white;
+    content-align-horizontal: center;
+    width: 100%;
+    height: 100%;
+}
diff --git a/docs/examples/styles/grid_columns.py b/docs/examples/styles/grid_columns.py
new file mode 100644
index 0000000000..05c772d561
--- /dev/null
+++ b/docs/examples/styles/grid_columns.py
@@ -0,0 +1,22 @@
+from textual.app import App
+from textual.containers import Grid
+from textual.widgets import Label
+
+
+class MyApp(App):
+    def compose(self):
+        yield Grid(
+            Label("1fr"),
+            Label("width = 16"),
+            Label("2fr"),
+            Label("1fr"),
+            Label("width = 16"),
+            Label("1fr"),
+            Label("width = 16"),
+            Label("2fr"),
+            Label("1fr"),
+            Label("width = 16"),
+        )
+
+
+app = MyApp(css_path="grid_columns.css")
diff --git a/docs/examples/styles/grid_gutter.css b/docs/examples/styles/grid_gutter.css
new file mode 100644
index 0000000000..e4f5240e88
--- /dev/null
+++ b/docs/examples/styles/grid_gutter.css
@@ -0,0 +1,11 @@
+Grid {
+    grid-size: 2 4;
+    grid-gutter: 1 2  /* (1)! */
+}
+
+Label {
+    border: round white;
+    content-align: center middle;
+    width: 100%;
+    height: 100%;
+}
diff --git a/docs/examples/styles/grid_gutter.py b/docs/examples/styles/grid_gutter.py
new file mode 100644
index 0000000000..363d4a37f7
--- /dev/null
+++ b/docs/examples/styles/grid_gutter.py
@@ -0,0 +1,20 @@
+from textual.app import App
+from textual.containers import Grid
+from textual.widgets import Label
+
+
+class MyApp(App):
+    def compose(self):
+        yield Grid(
+            Label("1"),
+            Label("2"),
+            Label("3"),
+            Label("4"),
+            Label("5"),
+            Label("6"),
+            Label("7"),
+            Label("8"),
+        )
+
+
+app = MyApp(css_path="grid_gutter.css")
diff --git a/docs/examples/styles/grid_rows.css b/docs/examples/styles/grid_rows.css
new file mode 100644
index 0000000000..bb29cb0646
--- /dev/null
+++ b/docs/examples/styles/grid_rows.css
@@ -0,0 +1,11 @@
+Grid {
+    grid-size: 2 5;
+    grid-rows: 1fr 6 25%;
+}
+
+Label {
+    border: round white;
+    content-align: center middle;
+    width: 100%;
+    height: 100%;
+}
diff --git a/docs/examples/styles/grid_rows.py b/docs/examples/styles/grid_rows.py
new file mode 100644
index 0000000000..ed06f7b6dd
--- /dev/null
+++ b/docs/examples/styles/grid_rows.py
@@ -0,0 +1,22 @@
+from textual.app import App
+from textual.containers import Grid
+from textual.widgets import Label
+
+
+class MyApp(App):
+    def compose(self):
+        yield Grid(
+            Label("1fr"),
+            Label("1fr"),
+            Label("height = 6"),
+            Label("height = 6"),
+            Label("25%"),
+            Label("25%"),
+            Label("1fr"),
+            Label("1fr"),
+            Label("height = 6"),
+            Label("height = 6"),
+        )
+
+
+app = MyApp(css_path="grid_rows.css")
diff --git a/docs/examples/styles/grid_size_both.css b/docs/examples/styles/grid_size_both.css
new file mode 100644
index 0000000000..8f3c2dce50
--- /dev/null
+++ b/docs/examples/styles/grid_size_both.css
@@ -0,0 +1,10 @@
+Grid {
+    grid-size: 2 4;  /* (1)! */
+}
+
+Label {
+    border: round white;
+    content-align: center middle;
+    width: 100%;
+    height: 100%;
+}
diff --git a/docs/examples/styles/grid_size_both.py b/docs/examples/styles/grid_size_both.py
new file mode 100644
index 0000000000..6383cc760f
--- /dev/null
+++ b/docs/examples/styles/grid_size_both.py
@@ -0,0 +1,17 @@
+from textual.app import App
+from textual.containers import Grid
+from textual.widgets import Label
+
+
+class MyApp(App):
+    def compose(self):
+        yield Grid(
+            Label("1"),
+            Label("2"),
+            Label("3"),
+            Label("4"),
+            Label("5"),
+        )
+
+
+app = MyApp(css_path="grid_size_both.css")
diff --git a/docs/examples/styles/grid_size_columns.css b/docs/examples/styles/grid_size_columns.css
new file mode 100644
index 0000000000..1fd94d6534
--- /dev/null
+++ b/docs/examples/styles/grid_size_columns.css
@@ -0,0 +1,10 @@
+Grid {
+    grid-size: 2;  /* (1)! */
+}
+
+Label {
+    border: round white;
+    content-align: center middle;
+    width: 100%;
+    height: 100%;
+}
diff --git a/docs/examples/styles/grid_size_columns.py b/docs/examples/styles/grid_size_columns.py
new file mode 100644
index 0000000000..06be941503
--- /dev/null
+++ b/docs/examples/styles/grid_size_columns.py
@@ -0,0 +1,17 @@
+from textual.app import App
+from textual.containers import Grid
+from textual.widgets import Label
+
+
+class MyApp(App):
+    def compose(self):
+        yield Grid(
+            Label("1"),
+            Label("2"),
+            Label("3"),
+            Label("4"),
+            Label("5"),
+        )
+
+
+app = MyApp(css_path="grid_size_columns.css")
diff --git a/docs/examples/styles/height_comparison.css b/docs/examples/styles/height_comparison.css
new file mode 100644
index 0000000000..ca2737e071
--- /dev/null
+++ b/docs/examples/styles/height_comparison.css
@@ -0,0 +1,34 @@
+#cells {
+    height: 2;       /* (1)! */
+}
+#percent {
+    height: 12.5%;   /* (2)! */
+}
+#w {
+    height: 5w;      /* (3)! */
+}
+#h {
+    height: 12.5h;   /* (4)! */
+}
+#vw {
+    height: 7.5vw;   /* (5)! */
+}
+#vh {
+    height: 12.5vh;  /* (6)! */
+}
+#auto {
+    height: auto;    /* (7)! */
+}
+#fr1 {
+    height: 1fr;     /* (8)! */
+}
+#fr2 {
+    height: 2fr;     /* (9)! */
+}
+
+VerticalRuler {
+    dock: right;
+    overflow: hidden;
+    width: auto;
+    background: $accent;
+}
diff --git a/docs/examples/styles/height_comparison.py b/docs/examples/styles/height_comparison.py
new file mode 100644
index 0000000000..b24f257aa4
--- /dev/null
+++ b/docs/examples/styles/height_comparison.py
@@ -0,0 +1,28 @@
+from textual.app import App
+from textual.containers import Vertical
+from textual.widgets import Placeholder, Label, Static
+
+
+class VerticalRuler(Static):
+    def compose(self):
+        ruler_text = "\n".join(map(str, range(1, 100)))
+        yield Label(ruler_text)
+
+
+class HeightComparisonApp(App):
+    def compose(self):
+        yield Vertical(
+            Placeholder(id="cells"),    # (1)!
+            Placeholder(id="percent"),
+            Placeholder(id="w"),
+            Placeholder(id="h"),
+            Placeholder(id="vw"),
+            Placeholder(id="vh"),
+            Placeholder(id="auto"),
+            Placeholder(id="fr1"),
+            Placeholder(id="fr2"),
+        )
+        yield VerticalRuler()
+
+
+app = HeightComparisonApp(css_path="height_comparison.css")
diff --git a/docs/examples/styles/layout.css b/docs/examples/styles/layout.css
index b0f7e33850..bb43aeb447 100644
--- a/docs/examples/styles/layout.css
+++ b/docs/examples/styles/layout.css
@@ -10,7 +10,7 @@
     height: auto;
 }
 
-Static {
+Label {
     margin: 1;
     width: 12;
     color: black;
diff --git a/docs/examples/styles/layout.py b/docs/examples/styles/layout.py
index f7c04e9844..bc87a4bb00 100644
--- a/docs/examples/styles/layout.py
+++ b/docs/examples/styles/layout.py
@@ -1,20 +1,20 @@
 from textual.app import App
 from textual.containers import Container
-from textual.widgets import Static
+from textual.widgets import Label
 
 
 class LayoutApp(App):
     def compose(self):
         yield Container(
-            Static("Layout"),
-            Static("Is"),
-            Static("Vertical"),
+            Label("Layout"),
+            Label("Is"),
+            Label("Vertical"),
             id="vertical-layout",
         )
         yield Container(
-            Static("Layout"),
-            Static("Is"),
-            Static("Horizontal"),
+            Label("Layout"),
+            Label("Is"),
+            Label("Horizontal"),
             id="horizontal-layout",
         )
 
diff --git a/docs/examples/styles/link_background.css b/docs/examples/styles/link_background.css
new file mode 100644
index 0000000000..94a31b2c7d
--- /dev/null
+++ b/docs/examples/styles/link_background.css
@@ -0,0 +1,11 @@
+#lbl1, #lbl2 {
+    link-background: red;  /* (1)! */
+}
+
+#lbl3 {
+    link-background: hsl(60,100%,50%) 50%;
+}
+
+#lbl4 {
+    link-background: $accent;
+}
diff --git a/docs/examples/styles/link_background.py b/docs/examples/styles/link_background.py
new file mode 100644
index 0000000000..dc21f32984
--- /dev/null
+++ b/docs/examples/styles/link_background.py
@@ -0,0 +1,25 @@
+from textual.app import App
+from textual.widgets import Label
+
+
+class LinkBackgroundApp(App):
+    def compose(self):
+        yield Label(
+            "Visit the [link=https://textualize.io]Textualize[/link] website.",
+            id="lbl1",  # (1)!
+        )
+        yield Label(
+            "Click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl2",  # (2)!
+        )
+        yield Label(
+            "You can also click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl3",  # (3)!
+        )
+        yield Label(
+            "[@click=app.quit]Exit this application.[/]",
+            id="lbl4",  # (4)!
+        )
+
+
+app = LinkBackgroundApp(css_path="link_background.css")
diff --git a/docs/examples/styles/link_color.css b/docs/examples/styles/link_color.css
new file mode 100644
index 0000000000..949af70786
--- /dev/null
+++ b/docs/examples/styles/link_color.css
@@ -0,0 +1,11 @@
+#lbl1, #lbl2 {
+    link-color: red;  /* (1)! */
+}
+
+#lbl3 {
+    link-color: hsl(60,100%,50%) 50%;
+}
+
+#lbl4 {
+    link-color: $accent;
+}
diff --git a/docs/examples/styles/link_color.py b/docs/examples/styles/link_color.py
new file mode 100644
index 0000000000..85cd36c18f
--- /dev/null
+++ b/docs/examples/styles/link_color.py
@@ -0,0 +1,25 @@
+from textual.app import App
+from textual.widgets import Label
+
+
+class LinkColorApp(App):
+    def compose(self):
+        yield Label(
+            "Visit the [link=https://textualize.io]Textualize[/link] website.",
+            id="lbl1",  # (1)!
+        )
+        yield Label(
+            "Click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl2",  # (2)!
+        )
+        yield Label(
+            "You can also click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl3",  # (3)!
+        )
+        yield Label(
+            "[@click=app.quit]Exit this application.[/]",
+            id="lbl4",  # (4)!
+        )
+
+
+app = LinkColorApp(css_path="link_color.css")
diff --git a/docs/examples/styles/link_hover_background.css b/docs/examples/styles/link_hover_background.css
new file mode 100644
index 0000000000..68d564ae23
--- /dev/null
+++ b/docs/examples/styles/link_hover_background.css
@@ -0,0 +1,11 @@
+#lbl1, #lbl2 {
+    link-hover-background: red;  /* (1)! */
+}
+
+#lbl3 {
+    link-hover-background: hsl(60,100%,50%) 50%;
+}
+
+#lbl4 {
+    /* Empty to show the default hover background */ /* (2)! */
+}
diff --git a/docs/examples/styles/link_hover_background.py b/docs/examples/styles/link_hover_background.py
new file mode 100644
index 0000000000..f1112b3558
--- /dev/null
+++ b/docs/examples/styles/link_hover_background.py
@@ -0,0 +1,25 @@
+from textual.app import App
+from textual.widgets import Label
+
+
+class LinkHoverBackgroundApp(App):
+    def compose(self):
+        yield Label(
+            "Visit the [link=https://textualize.io]Textualize[/link] website.",
+            id="lbl1",  # (1)!
+        )
+        yield Label(
+            "Click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl2",  # (2)!
+        )
+        yield Label(
+            "You can also click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl3",  # (3)!
+        )
+        yield Label(
+            "[@click=app.quit]Exit this application.[/]",
+            id="lbl4",  # (4)!
+        )
+
+
+app = LinkHoverBackgroundApp(css_path="link_hover_background.css")
diff --git a/docs/examples/styles/link_hover_color.css b/docs/examples/styles/link_hover_color.css
new file mode 100644
index 0000000000..234184f474
--- /dev/null
+++ b/docs/examples/styles/link_hover_color.css
@@ -0,0 +1,11 @@
+#lbl1, #lbl2 {
+    link-hover-color: red;  /* (1)! */
+}
+
+#lbl3 {
+    link-hover-color: hsl(60,100%,50%) 50%;
+}
+
+#lbl4 {
+    link-hover-color: black;
+}
diff --git a/docs/examples/styles/link_hover_color.py b/docs/examples/styles/link_hover_color.py
new file mode 100644
index 0000000000..56093563de
--- /dev/null
+++ b/docs/examples/styles/link_hover_color.py
@@ -0,0 +1,25 @@
+from textual.app import App
+from textual.widgets import Label
+
+
+class LinkHoverColorApp(App):
+    def compose(self):
+        yield Label(
+            "Visit the [link=https://textualize.io]Textualize[/link] website.",
+            id="lbl1",  # (1)!
+        )
+        yield Label(
+            "Click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl2",  # (2)!
+        )
+        yield Label(
+            "You can also click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl3",  # (3)!
+        )
+        yield Label(
+            "[@click=app.quit]Exit this application.[/]",
+            id="lbl4",  # (4)!
+        )
+
+
+app = LinkHoverColorApp(css_path="link_hover_color.css")
diff --git a/docs/examples/styles/link_hover_style.css b/docs/examples/styles/link_hover_style.css
new file mode 100644
index 0000000000..169e69d290
--- /dev/null
+++ b/docs/examples/styles/link_hover_style.css
@@ -0,0 +1,11 @@
+#lbl1, #lbl2 {
+    link-hover-style: bold italic;  /* (1)! */
+}
+
+#lbl3 {
+    link-hover-style: reverse strike;
+}
+
+#lbl4 {
+    link-hover-style: bold;
+}
diff --git a/docs/examples/styles/link_hover_style.py b/docs/examples/styles/link_hover_style.py
new file mode 100644
index 0000000000..6a6ef3dbac
--- /dev/null
+++ b/docs/examples/styles/link_hover_style.py
@@ -0,0 +1,25 @@
+from textual.app import App
+from textual.widgets import Label
+
+
+class LinkHoverStyleApp(App):
+    def compose(self):
+        yield Label(
+            "Visit the [link=https://textualize.io]Textualize[/link] website.",
+            id="lbl1",  # (1)!
+        )
+        yield Label(
+            "Click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl2",  # (2)!
+        )
+        yield Label(
+            "You can also click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl3",  # (3)!
+        )
+        yield Label(
+            "[@click=app.quit]Exit this application.[/]",
+            id="lbl4",  # (4)!
+        )
+
+
+app = LinkHoverStyleApp(css_path="link_hover_style.css")
diff --git a/docs/examples/styles/link_style.css b/docs/examples/styles/link_style.css
new file mode 100644
index 0000000000..63240c91a3
--- /dev/null
+++ b/docs/examples/styles/link_style.css
@@ -0,0 +1,11 @@
+#lbl1, #lbl2 {
+    link-style: bold italic;  /* (1)! */
+}
+
+#lbl3 {
+    link-style: reverse strike;
+}
+
+#lbl4 {
+    link-style: bold;
+}
diff --git a/docs/examples/styles/link_style.py b/docs/examples/styles/link_style.py
new file mode 100644
index 0000000000..5ed9f12a9c
--- /dev/null
+++ b/docs/examples/styles/link_style.py
@@ -0,0 +1,25 @@
+from textual.app import App
+from textual.widgets import Label
+
+
+class LinkStyleApp(App):
+    def compose(self):
+        yield Label(
+            "Visit the [link=https://textualize.io]Textualize[/link] website.",
+            id="lbl1",  # (1)!
+        )
+        yield Label(
+            "Click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl2",  # (2)!
+        )
+        yield Label(
+            "You can also click [@click=app.bell]here[/] for the bell sound.",
+            id="lbl3",  # (3)!
+        )
+        yield Label(
+            "[@click=app.quit]Exit this application.[/]",
+            id="lbl4",  # (4)!
+        )
+
+
+app = LinkStyleApp(css_path="link_style.css")
diff --git a/docs/examples/styles/margin.css b/docs/examples/styles/margin.css
index e1b01fa030..296a881743 100644
--- a/docs/examples/styles/margin.css
+++ b/docs/examples/styles/margin.css
@@ -3,8 +3,8 @@ Screen {
     color: black;
 }
 
-Static {
-    margin: 4 8;  
-    background: blue 20%;  
+Label {
+    margin: 4 8;
+    background: blue 20%;
     border: blue wide;
-}    
+}
diff --git a/docs/examples/styles/margin.py b/docs/examples/styles/margin.py
index 3e6129ead8..7551d58656 100644
--- a/docs/examples/styles/margin.py
+++ b/docs/examples/styles/margin.py
@@ -1,5 +1,5 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 TEXT = """I must not fear.
 Fear is the mind-killer.
@@ -12,7 +12,7 @@
 
 class MarginApp(App):
     def compose(self):
-        yield Static(TEXT)
+        yield Label(TEXT)
 
 
 app = MarginApp(css_path="margin.css")
diff --git a/docs/examples/styles/margin_all.css b/docs/examples/styles/margin_all.css
new file mode 100644
index 0000000000..a6b1e7dc31
--- /dev/null
+++ b/docs/examples/styles/margin_all.css
@@ -0,0 +1,54 @@
+Screen {
+    background: $background;
+}
+
+Grid {
+    grid-size: 4;
+    grid-gutter: 1 2;
+}
+
+Placeholder {
+    width: 100%;
+    height: 100%;
+}
+
+Container {
+    width: 100%;
+    height: 100%;
+}
+
+.bordered {
+    border: white round;
+}
+
+#p1 {
+    /* default is no margin */
+}
+
+#p2 {
+    margin: 1;
+}
+
+#p3 {
+    margin: 1 5;
+}
+
+#p4 {
+    margin: 1 1 2 6;
+}
+
+#p5 {
+    margin-top: 4;
+}
+
+#p6 {
+    margin-right: 3;
+}
+
+#p7 {
+    margin-bottom: 4;
+}
+
+#p8 {
+    margin-left: 3;
+}
diff --git a/docs/examples/styles/margin_all.py b/docs/examples/styles/margin_all.py
new file mode 100644
index 0000000000..b88705f263
--- /dev/null
+++ b/docs/examples/styles/margin_all.py
@@ -0,0 +1,20 @@
+from textual.app import App
+from textual.containers import Container, Grid
+from textual.widgets import Placeholder
+
+
+class MarginAllApp(App):
+    def compose(self):
+        yield Grid(
+            Container(Placeholder("no margin", id="p1"), classes="bordered"),
+            Container(Placeholder("margin: 1", id="p2"), classes="bordered"),
+            Container(Placeholder("margin: 1 5", id="p3"), classes="bordered"),
+            Container(Placeholder("margin: 1 1 2 6", id="p4"), classes="bordered"),
+            Container(Placeholder("margin-top: 4", id="p5"), classes="bordered"),
+            Container(Placeholder("margin-right: 3", id="p6"), classes="bordered"),
+            Container(Placeholder("margin-bottom: 4", id="p7"), classes="bordered"),
+            Container(Placeholder("margin-left: 3", id="p8"), classes="bordered"),
+        )
+
+
+app = MarginAllApp(css_path="margin_all.css")
diff --git a/docs/examples/styles/max_height.css b/docs/examples/styles/max_height.css
new file mode 100644
index 0000000000..7bbc5966ef
--- /dev/null
+++ b/docs/examples/styles/max_height.css
@@ -0,0 +1,25 @@
+Horizontal {
+    height: 100%;
+    width: 100%;
+}
+
+Placeholder {
+    height: 100%;
+    width: 1fr;
+}
+
+#p1 {
+    max-height: 10w;
+}
+
+#p2 {
+    max-height: 999;  /* (1)! */
+}
+
+#p3 {
+    max-height: 50%;
+}
+
+#p4 {
+    max-height: 10;
+}
diff --git a/docs/examples/styles/max_height.py b/docs/examples/styles/max_height.py
new file mode 100644
index 0000000000..7f3a00fdae
--- /dev/null
+++ b/docs/examples/styles/max_height.py
@@ -0,0 +1,16 @@
+from textual.app import App
+from textual.containers import Horizontal
+from textual.widgets import Placeholder
+
+
+class MaxHeightApp(App):
+    def compose(self):
+        yield Horizontal(
+            Placeholder("max-height: 10w", id="p1"),
+            Placeholder("max-height: 999", id="p2"),
+            Placeholder("max-height: 50%", id="p3"),
+            Placeholder("max-height: 10", id="p4"),
+        )
+
+
+app = MaxHeightApp(css_path="max_height.css")
diff --git a/docs/examples/styles/max_width.css b/docs/examples/styles/max_width.css
new file mode 100644
index 0000000000..a32353a78b
--- /dev/null
+++ b/docs/examples/styles/max_width.css
@@ -0,0 +1,25 @@
+Horizontal {
+    height: 100%;
+    width: 100%;
+}
+
+Placeholder {
+    width: 100%;
+    height: 1fr;
+}
+
+#p1 {
+    max-width: 50h;
+}
+
+#p2 {
+    max-width: 999;  /* (1)! */
+}
+
+#p3 {
+    max-width: 50%;
+}
+
+#p4 {
+    max-width: 30;
+}
diff --git a/docs/examples/styles/max_width.py b/docs/examples/styles/max_width.py
new file mode 100644
index 0000000000..0ee440a923
--- /dev/null
+++ b/docs/examples/styles/max_width.py
@@ -0,0 +1,16 @@
+from textual.app import App
+from textual.containers import Vertical
+from textual.widgets import Placeholder
+
+
+class MaxWidthApp(App):
+    def compose(self):
+        yield Vertical(
+            Placeholder("max-width: 50h", id="p1"),
+            Placeholder("max-width: 999", id="p2"),
+            Placeholder("max-width: 50%", id="p3"),
+            Placeholder("max-width: 30", id="p4"),
+        )
+
+
+app = MaxWidthApp(css_path="max_width.css")
diff --git a/docs/examples/styles/min_height.css b/docs/examples/styles/min_height.css
new file mode 100644
index 0000000000..ca4d2853f3
--- /dev/null
+++ b/docs/examples/styles/min_height.css
@@ -0,0 +1,26 @@
+Horizontal {
+    height: 100%;
+    width: 100%;
+    overflow-y: auto;
+}
+
+Placeholder {
+    width: 1fr;
+    height: 50%;
+}
+
+#p1 {
+    min-height: 25%;  /* (1)! */
+}
+
+#p2 {
+    min-height: 75%;
+}
+
+#p3 {
+    min-height: 30;
+}
+
+#p4 {
+    min-height: 40w;
+}
diff --git a/docs/examples/styles/min_height.py b/docs/examples/styles/min_height.py
new file mode 100644
index 0000000000..b6e02dedaf
--- /dev/null
+++ b/docs/examples/styles/min_height.py
@@ -0,0 +1,16 @@
+from textual.app import App
+from textual.containers import Horizontal
+from textual.widgets import Placeholder
+
+
+class MinHeightApp(App):
+    def compose(self):
+        yield Horizontal(
+            Placeholder("min-height: 25%", id="p1"),
+            Placeholder("min-height: 75%", id="p2"),
+            Placeholder("min-height: 30", id="p3"),
+            Placeholder("min-height: 40w", id="p4"),
+        )
+
+
+app = MinHeightApp(css_path="min_height.css")
diff --git a/docs/examples/styles/min_width.css b/docs/examples/styles/min_width.css
new file mode 100644
index 0000000000..43dd8400ac
--- /dev/null
+++ b/docs/examples/styles/min_width.css
@@ -0,0 +1,26 @@
+Vertical {
+    height: 100%;
+    width: 100%;
+    overflow-x: auto;
+}
+
+Placeholder {
+    height: 1fr;
+    width: 50%;
+}
+
+#p1 {
+    min-width: 25%;  /* (1)! */
+}
+
+#p2 {
+    min-width: 75%;
+}
+
+#p3 {
+    min-width: 100;
+}
+
+#p4 {
+    min-width: 400h;
+}
diff --git a/docs/examples/styles/min_width.py b/docs/examples/styles/min_width.py
new file mode 100644
index 0000000000..25195c61d7
--- /dev/null
+++ b/docs/examples/styles/min_width.py
@@ -0,0 +1,16 @@
+from textual.app import App
+from textual.containers import Vertical
+from textual.widgets import Placeholder
+
+
+class MinWidthApp(App):
+    def compose(self):
+        yield Vertical(
+            Placeholder("min-width: 25%", id="p1"),
+            Placeholder("min-width: 75%", id="p2"),
+            Placeholder("min-width: 100", id="p3"),
+            Placeholder("min-width: 400h", id="p4"),
+        )
+
+
+app = MinWidthApp(css_path="min_width.css")
diff --git a/docs/examples/styles/offset.css b/docs/examples/styles/offset.css
index d0a54a3550..673f9fe1cb 100644
--- a/docs/examples/styles/offset.css
+++ b/docs/examples/styles/offset.css
@@ -3,10 +3,10 @@ Screen {
     color: black;
     layout: horizontal;
 }
-Static {             
+Label {
     width: 20;
     height: 10;
-    content-align: center middle; 
+    content-align: center middle;
 }
 
 .paul {
@@ -24,7 +24,7 @@ Static {
 }
 
 .chani {
-    offset: 0 5;
+    offset: 0 -2;
     background: blue 20%;
     border: outer blue;
     color: blue;
diff --git a/docs/examples/styles/offset.py b/docs/examples/styles/offset.py
index d850b37787..337e1112a1 100644
--- a/docs/examples/styles/offset.py
+++ b/docs/examples/styles/offset.py
@@ -1,12 +1,12 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 
 class OffsetApp(App):
     def compose(self):
-        yield Static("Paul (offset 8 2)", classes="paul")
-        yield Static("Duncan (offset 4 10)", classes="duncan")
-        yield Static("Chani (offset 0 5)", classes="chani")
+        yield Label("Paul (offset 8 2)", classes="paul")
+        yield Label("Duncan (offset 4 10)", classes="duncan")
+        yield Label("Chani (offset 0 -2)", classes="chani")
 
 
 app = OffsetApp(css_path="offset.css")
diff --git a/docs/examples/styles/opacity.css b/docs/examples/styles/opacity.css
index 15d0594807..1a59b197b8 100644
--- a/docs/examples/styles/opacity.css
+++ b/docs/examples/styles/opacity.css
@@ -19,10 +19,11 @@
 }
 
 Screen {
-    background: antiquewhite;
+    background: black;
 }
 
-Static {
+Label {
+    width: 100%;
     height: 1fr;
     border: outer dodgerblue;
     background: lightseagreen;
diff --git a/docs/examples/styles/opacity.py b/docs/examples/styles/opacity.py
index d723b1d848..5a079fb642 100644
--- a/docs/examples/styles/opacity.py
+++ b/docs/examples/styles/opacity.py
@@ -1,14 +1,14 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 
 class OpacityApp(App):
     def compose(self):
-        yield Static("opacity: 0%", id="zero-opacity")
-        yield Static("opacity: 25%", id="quarter-opacity")
-        yield Static("opacity: 50%", id="half-opacity")
-        yield Static("opacity: 75%", id="three-quarter-opacity")
-        yield Static("opacity: 100%", id="full-opacity")
+        yield Label("opacity: 0%", id="zero-opacity")
+        yield Label("opacity: 25%", id="quarter-opacity")
+        yield Label("opacity: 50%", id="half-opacity")
+        yield Label("opacity: 75%", id="three-quarter-opacity")
+        yield Label("opacity: 100%", id="full-opacity")
 
 
 app = OpacityApp(css_path="opacity.css")
diff --git a/docs/examples/styles/outline.css b/docs/examples/styles/outline.css
index 487270c6a1..b422b5332c 100644
--- a/docs/examples/styles/outline.css
+++ b/docs/examples/styles/outline.css
@@ -2,7 +2,7 @@ Screen {
     background: white;
     color: black;
 }
-Static {
+Label {
     margin: 4 8;
     background: green 20%;
     outline: wide green;
diff --git a/docs/examples/styles/outline.py b/docs/examples/styles/outline.py
index e64b11dc23..5f82c85dc0 100644
--- a/docs/examples/styles/outline.py
+++ b/docs/examples/styles/outline.py
@@ -1,5 +1,5 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 
 TEXT = """I must not fear.
@@ -13,7 +13,7 @@
 
 class OutlineApp(App):
     def compose(self):
-        yield Static(TEXT)
+        yield Label(TEXT)
 
 
 app = OutlineApp(css_path="outline.css")
diff --git a/docs/examples/styles/outline_vs_border.css b/docs/examples/styles/outline_vs_border.css
new file mode 100644
index 0000000000..8153bf0487
--- /dev/null
+++ b/docs/examples/styles/outline_vs_border.css
@@ -0,0 +1,11 @@
+Label {
+    height: 8;
+}
+
+.outline {
+    outline: $error round;
+}
+
+.border {
+    border: $success heavy;
+}
diff --git a/docs/examples/styles/outline_vs_border.py b/docs/examples/styles/outline_vs_border.py
new file mode 100644
index 0000000000..62b072ebd0
--- /dev/null
+++ b/docs/examples/styles/outline_vs_border.py
@@ -0,0 +1,21 @@
+from textual.app import App
+from textual.widgets import Label
+
+
+TEXT = """I must not fear.
+Fear is the mind-killer.
+Fear is the little-death that brings total obliteration.
+I will face my fear.
+I will permit it to pass over me and through me.
+And when it has gone past, I will turn the inner eye to see its path.
+Where the fear has gone there will be nothing. Only I will remain."""
+
+
+class OutlineBorderApp(App):
+    def compose(self):
+        yield Label(TEXT, classes="outline")
+        yield Label(TEXT, classes="border")
+        yield Label(TEXT, classes="outline border")
+
+
+app = OutlineBorderApp(css_path="outline_vs_border.css")
diff --git a/docs/examples/styles/padding.css b/docs/examples/styles/padding.css
index 4c558895b8..68ad843851 100644
--- a/docs/examples/styles/padding.css
+++ b/docs/examples/styles/padding.css
@@ -3,7 +3,7 @@ Screen {
     color: blue;
 }
 
-Static {
+Label {
     padding: 4 8;  
     background: blue 20%;  
 }    
diff --git a/docs/examples/styles/padding.py b/docs/examples/styles/padding.py
index 4893838c13..13c43381ab 100644
--- a/docs/examples/styles/padding.py
+++ b/docs/examples/styles/padding.py
@@ -1,5 +1,5 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 TEXT = """I must not fear.
 Fear is the mind-killer.
@@ -12,7 +12,7 @@
 
 class PaddingApp(App):
     def compose(self):
-        yield Static(TEXT)
+        yield Label(TEXT)
 
 
 app = PaddingApp(css_path="padding.css")
diff --git a/docs/examples/styles/row_span.css b/docs/examples/styles/row_span.css
new file mode 100644
index 0000000000..195ca2ac77
--- /dev/null
+++ b/docs/examples/styles/row_span.css
@@ -0,0 +1,30 @@
+#p1 {
+    row-span: 4;
+}
+#p2 {
+    row-span: 3;
+}
+#p3 {
+    row-span: 2;
+}
+#p4 {
+    row-span: 1;  /* Didn't need to be set explicitly. */
+}
+#p5 {
+    row-span: 3;
+}
+#p6 {
+    row-span: 2;
+}
+#p7 {
+    /* Default value is 1. */
+}
+
+Grid {
+    grid-size: 4 4;
+    grid-gutter: 1 2;
+}
+
+Placeholder {
+    height: 100%;
+}
diff --git a/docs/examples/styles/row_span.py b/docs/examples/styles/row_span.py
new file mode 100644
index 0000000000..826dc13ebe
--- /dev/null
+++ b/docs/examples/styles/row_span.py
@@ -0,0 +1,19 @@
+from textual.app import App
+from textual.containers import Grid
+from textual.widgets import Placeholder
+
+
+class MyApp(App):
+    def compose(self):
+        yield Grid(
+            Placeholder(id="p1"),
+            Placeholder(id="p2"),
+            Placeholder(id="p3"),
+            Placeholder(id="p4"),
+            Placeholder(id="p5"),
+            Placeholder(id="p6"),
+            Placeholder(id="p7"),
+        )
+
+
+app = MyApp(css_path="row_span.css")
diff --git a/docs/examples/styles/scrollbar_corner_color.css b/docs/examples/styles/scrollbar_corner_color.css
new file mode 100644
index 0000000000..3cf3823710
--- /dev/null
+++ b/docs/examples/styles/scrollbar_corner_color.css
@@ -0,0 +1,4 @@
+Screen {
+    overflow: auto auto;
+    scrollbar-corner-color: white;
+}
diff --git a/docs/examples/styles/scrollbar_corner_color.py b/docs/examples/styles/scrollbar_corner_color.py
new file mode 100644
index 0000000000..9e20fedbb8
--- /dev/null
+++ b/docs/examples/styles/scrollbar_corner_color.py
@@ -0,0 +1,19 @@
+from textual.app import App
+from textual.widgets import Label
+
+TEXT = """I must not fear.
+Fear is the mind-killer.
+Fear is the little-death that brings total obliteration.
+I will face my fear.
+I will permit it to pass over me and through me.
+And when it has gone past, I will turn the inner eye to see its path.
+Where the fear has gone there will be nothing. Only I will remain.
+"""
+
+
+class ScrollbarCornerColorApp(App):
+    def compose(self):
+        yield Label(TEXT.replace("\n", " ") + "\n" + TEXT * 10)
+
+
+app = ScrollbarCornerColorApp(css_path="scrollbar_corner_color.css")
diff --git a/docs/examples/styles/scrollbar_size.css b/docs/examples/styles/scrollbar_size.css
index b119f07a3e..4165f287ca 100644
--- a/docs/examples/styles/scrollbar_size.css
+++ b/docs/examples/styles/scrollbar_size.css
@@ -4,7 +4,7 @@ Screen {
     layout: horizontal;
 }
 
-Static {
+Label {
     padding: 1 2;
     width: 200;
 }
diff --git a/docs/examples/styles/scrollbar_size.py b/docs/examples/styles/scrollbar_size.py
index 97facad708..1bbcec572b 100644
--- a/docs/examples/styles/scrollbar_size.py
+++ b/docs/examples/styles/scrollbar_size.py
@@ -1,6 +1,6 @@
 from textual.app import App
 from textual.containers import Vertical
-from textual.widgets import Static
+from textual.widgets import Label
 
 TEXT = """I must not fear.
 Fear is the mind-killer.
@@ -14,7 +14,7 @@
 
 class ScrollbarApp(App):
     def compose(self):
-        yield Vertical(Static(TEXT * 5), classes="panel")
+        yield Vertical(Label(TEXT * 5), classes="panel")
 
 
 app = ScrollbarApp(css_path="scrollbar_size.css")
diff --git a/docs/examples/styles/scrollbar_size2.css b/docs/examples/styles/scrollbar_size2.css
new file mode 100644
index 0000000000..6054ceed1c
--- /dev/null
+++ b/docs/examples/styles/scrollbar_size2.css
@@ -0,0 +1,18 @@
+Container {
+    width: 1fr;
+}
+
+#v1 {
+    scrollbar-size: 5 1;
+    background: red 20%;
+}
+
+#v2 {
+    scrollbar-size-vertical: 1;
+    background: green 20%;
+}
+
+#v3 {
+    scrollbar-size-horizontal: 5;
+    background: blue 20%;
+}
diff --git a/docs/examples/styles/scrollbar_size2.py b/docs/examples/styles/scrollbar_size2.py
new file mode 100644
index 0000000000..66bd7e397a
--- /dev/null
+++ b/docs/examples/styles/scrollbar_size2.py
@@ -0,0 +1,24 @@
+from textual.app import App
+from textual.containers import Horizontal, Container
+from textual.widgets import Label
+
+TEXT = """I must not fear.
+Fear is the mind-killer.
+Fear is the little-death that brings total obliteration.
+I will face my fear.
+I will permit it to pass over me and through me.
+And when it has gone past, I will turn the inner eye to see its path.
+Where the fear has gone there will be nothing. Only I will remain.
+"""
+
+
+class ScrollbarApp(App):
+    def compose(self):
+        yield Horizontal(
+            Container(Label(TEXT * 5), id="v1"),
+            Container(Label(TEXT * 5), id="v2"),
+            Container(Label(TEXT * 5), id="v3"),
+        )
+
+
+app = ScrollbarApp(css_path="scrollbar_size2.css")
diff --git a/docs/examples/styles/scrollbars.css b/docs/examples/styles/scrollbars.css
index 8399bd0773..b949522744 100644
--- a/docs/examples/styles/scrollbars.css
+++ b/docs/examples/styles/scrollbars.css
@@ -1,23 +1,14 @@
-Screen {
-    background: #212121;
-    color: white 80%;
-    layout: horizontal;
+Label {
+    width: 150%;
+    height: 150%;
 }
 
-Static {
-    padding: 1 2;
-}
-
-.panel1 {
-    width: 1fr;
+.right {
+    scrollbar-background: red;
     scrollbar-color: green;
-    scrollbar-background: #bbb;
-    padding: 1 2;        
-} 
+    scrollbar-corner-color: blue;
+}
 
-.panel2 {
-    width: 1fr;
-    scrollbar-color: yellow;
-    scrollbar-background: purple;
-    padding: 1 2;
-}   
+Horizontal > Container {
+    width: 50%;
+}
diff --git a/docs/examples/styles/scrollbars.py b/docs/examples/styles/scrollbars.py
index f426c0d57a..371027eccc 100644
--- a/docs/examples/styles/scrollbars.py
+++ b/docs/examples/styles/scrollbars.py
@@ -1,6 +1,6 @@
 from textual.app import App
-from textual.containers import Vertical
-from textual.widgets import Static
+from textual.containers import Horizontal, Container
+from textual.widgets import Label
 
 TEXT = """I must not fear.
 Fear is the mind-killer.
@@ -14,8 +14,10 @@
 
 class ScrollbarApp(App):
     def compose(self):
-        yield Vertical(Static(TEXT * 5), classes="panel1")
-        yield Vertical(Static(TEXT * 5), classes="panel2")
+        yield Horizontal(
+            Container(Label(TEXT * 10)),
+            Container(Label(TEXT * 10), classes="right"),
+        )
 
 
 app = ScrollbarApp(css_path="scrollbars.css")
diff --git a/docs/examples/styles/scrollbars2.css b/docs/examples/styles/scrollbars2.css
new file mode 100644
index 0000000000..4e7fa8145e
--- /dev/null
+++ b/docs/examples/styles/scrollbars2.css
@@ -0,0 +1,8 @@
+Screen {
+    scrollbar-background: blue;
+    scrollbar-background-active: red;
+    scrollbar-background-hover: purple;
+    scrollbar-color: cyan;
+    scrollbar-color-active: yellow;
+    scrollbar-color-hover: pink;
+}
diff --git a/docs/examples/styles/scrollbars2.py b/docs/examples/styles/scrollbars2.py
new file mode 100644
index 0000000000..988b871300
--- /dev/null
+++ b/docs/examples/styles/scrollbars2.py
@@ -0,0 +1,19 @@
+from textual.app import App
+from textual.widgets import Label
+
+TEXT = """I must not fear.
+Fear is the mind-killer.
+Fear is the little-death that brings total obliteration.
+I will face my fear.
+I will permit it to pass over me and through me.
+And when it has gone past, I will turn the inner eye to see its path.
+Where the fear has gone there will be nothing. Only I will remain.
+"""
+
+
+class Scrollbar2App(App):
+    def compose(self):
+        yield Label(TEXT * 10)
+
+
+app = Scrollbar2App(css_path="scrollbars2.css")
diff --git a/docs/examples/styles/text_align.css b/docs/examples/styles/text_align.css
index c594254d6b..32714ba237 100644
--- a/docs/examples/styles/text_align.css
+++ b/docs/examples/styles/text_align.css
@@ -1,24 +1,29 @@
 #one {
-  text-align: left;
-  background: lightblue;
-
+    text-align: left;
+    background: lightblue;
 }
 
 #two {
-  text-align: center;
-  background: indianred;
+    text-align: center;
+    background: indianred;
 }
 
 #three {
-  text-align: right;
-  background: palegreen;
+    text-align: right;
+    background: palegreen;
 }
 
 #four {
-  text-align: justify;
-  background: palevioletred;
+    text-align: justify;
+    background: palevioletred;
+}
+
+Label {
+    padding: 1 2;
+    height: 100%;
+    color: auto;
 }
 
-Static {
-  padding: 1;
+Grid {
+    grid-size: 2 2;
 }
diff --git a/docs/examples/styles/text_align.py b/docs/examples/styles/text_align.py
index 27e2892fa5..0c72a17f36 100644
--- a/docs/examples/styles/text_align.py
+++ b/docs/examples/styles/text_align.py
@@ -1,7 +1,6 @@
-from __future__ import annotations
-
-from textual.app import App, ComposeResult
-from textual.widgets import Static
+from textual.app import App
+from textual.containers import Grid
+from textual.widgets import Label
 
 TEXT = (
     "I must not fear. Fear is the mind-killer. Fear is the little-death that "
@@ -11,18 +10,13 @@
 
 
 class TextAlign(App):
-    def compose(self) -> ComposeResult:
-        left = Static("[b]Left aligned[/]\n" + TEXT, id="one")
-        yield left
-
-        right = Static("[b]Center aligned[/]\n" + TEXT, id="two")
-        yield right
-
-        center = Static("[b]Right aligned[/]\n" + TEXT, id="three")
-        yield center
-
-        full = Static("[b]Justified[/]\n" + TEXT, id="four")
-        yield full
+    def compose(self):
+        yield Grid(
+            Label("[b]Left aligned[/]\n" + TEXT, id="one"),
+            Label("[b]Center aligned[/]\n" + TEXT, id="two"),
+            Label("[b]Right aligned[/]\n" + TEXT, id="three"),
+            Label("[b]Justified[/]\n" + TEXT, id="four"),
+        )
 
 
 app = TextAlign(css_path="text_align.css")
diff --git a/docs/examples/styles/text_opacity.css b/docs/examples/styles/text_opacity.css
index 882cc8acb3..56ae0e576e 100644
--- a/docs/examples/styles/text_opacity.css
+++ b/docs/examples/styles/text_opacity.css
@@ -18,8 +18,9 @@
     text-opacity: 100%;
 }
 
-Static {
+Label {
     height: 1fr;
+    width: 100%;
     text-align: center;
     text-style: bold;
 }
diff --git a/docs/examples/styles/text_opacity.py b/docs/examples/styles/text_opacity.py
index a2e9dcff2e..351093e670 100644
--- a/docs/examples/styles/text_opacity.py
+++ b/docs/examples/styles/text_opacity.py
@@ -1,14 +1,14 @@
 from textual.app import App
-from textual.widgets import Static
+from textual.widgets import Label
 
 
 class TextOpacityApp(App):
     def compose(self):
-        yield Static("text-opacity: 0%", id="zero-opacity")
-        yield Static("text-opacity: 25%", id="quarter-opacity")
-        yield Static("text-opacity: 50%", id="half-opacity")
-        yield Static("text-opacity: 75%", id="three-quarter-opacity")
-        yield Static("text-opacity: 100%", id="full-opacity")
+        yield Label("text-opacity: 0%", id="zero-opacity")
+        yield Label("text-opacity: 25%", id="quarter-opacity")
+        yield Label("text-opacity: 50%", id="half-opacity")
+        yield Label("text-opacity: 75%", id="three-quarter-opacity")
+        yield Label("text-opacity: 100%", id="full-opacity")
 
 
 app = TextOpacityApp(css_path="text_opacity.css")
diff --git a/docs/guide/layout.md b/docs/guide/layout.md
index 495cb6f864..94405d8379 100644
--- a/docs/guide/layout.md
+++ b/docs/guide/layout.md
@@ -503,7 +503,7 @@ However, in this case, both `#box1` and `#box2` are assigned to layers which def
 
 === "layers.css"
 
-    ```sass hl_lines="3 15 19"
+    ```sass hl_lines="3 14 19"
     --8<-- "docs/examples/guide/layout/layers.css"
     ```
 
diff --git a/docs/reference/index.md b/docs/reference/index.md
index 1ddd462b16..607587a59b 100644
--- a/docs/reference/index.md
+++ b/docs/reference/index.md
@@ -4,6 +4,15 @@ Welcome to the Textual Reference.
 
 <div class="grid cards" markdown>
 
+-   :octicons-book-16:{ .lg .middle } __CSS Types__
+
+    ---
+
+    CSS Types are the data types that CSS [styles](../styles/index.md) accept in their rules.
+
+    :octicons-arrow-right-24: [CSS Types Reference](../css_types/index.md)
+
+
 -   :octicons-book-16:{ .lg .middle } __Events__
 
     ---
diff --git a/docs/snippets/syntax_block_end.md b/docs/snippets/syntax_block_end.md
new file mode 100644
index 0000000000..a100faef8d
--- /dev/null
+++ b/docs/snippets/syntax_block_end.md
@@ -0,0 +1,2 @@
+</pre></div>
+<!-- Include this snippet when ending a code block that shows the syntax of a CSS rule. -->
diff --git a/docs/snippets/syntax_block_start.md b/docs/snippets/syntax_block_start.md
new file mode 100644
index 0000000000..3eddc9775e
--- /dev/null
+++ b/docs/snippets/syntax_block_start.md
@@ -0,0 +1,2 @@
+<!-- Include this snippet when starting a code block that shows the syntax of a CSS rule. -->
+<div class="highlight" style="padding: 0.25em 1.15em; background: var(--md-code-bg-color);"><pre>
diff --git a/docs/snippets/type_syntax/_template.md b/docs/snippets/type_syntax/_template.md
new file mode 100644
index 0000000000..77697f721e
--- /dev/null
+++ b/docs/snippets/type_syntax/_template.md
@@ -0,0 +1,39 @@
+<!--
+This is the template file for a syntax snippet of a Textual CSS type.
+The comments below illustrate some common patterns.
+-->
+
+<!--
+For a simple type like <integer>:
+
+Describe the type in a short paragraph with an absolute link to the type page.
+E.g., “The [`<my-type>`](/css_types/my_type) type is such and such with sprinkles on top.”
+-->
+
+<!--
+For a type with many different values like <color>:
+
+Introduce the type with a link to [`<my-type>`](/css_types/my_type).
+Then, a bullet list with the variants accepted:
+
+ - you can create this type with X Y Z;
+ - you can also do A B C; and
+ - also use D E F.
+
+Consider ending with a link to the code/API that serves as ground truth for what values are accepted.
+-->
+
+<!--
+For a type that accepts specific options like <border>:
+
+Add a sentence and a table. Consider ordering values in alphabetical order if there is no other obvious ordering. See below:
+
+The [`<my-type>`](/css_types/my_type) type can take any of the following values:
+
+| Value         | Description                                   |
+|---------------|-----------------------------------------------|
+| `abc`         | Describe here.                                |
+| `other val`   | Describe this one also.                       |
+| `value three` | Please use full stops.                        |
+| `zyx`         | Describe the value without assuming any rule. |
+-->
diff --git a/docs/snippets/type_syntax/border.md b/docs/snippets/type_syntax/border.md
new file mode 100644
index 0000000000..519507bdd5
--- /dev/null
+++ b/docs/snippets/type_syntax/border.md
@@ -0,0 +1,19 @@
+The [`<border>`](/css_types/border) type can take any of the following values:
+
+| Border type | Description                                              |
+|-------------|----------------------------------------------------------|
+| `ascii`   | A border with plus, hyphen, and vertical bar characters. |
+| `blank`   | A blank border (reserves space for a border).            |
+| `dashed`  | Dashed line border.                                      |
+| `double`  | Double lined border.                                     |
+| `heavy`   | Heavy border.                                            |
+| `hidden`  | Alias for "none".                                        |
+| `hkey`    | Horizontal key-line border.                              |
+| `inner`   | Thick solid border.                                      |
+| `none`    | Disabled border.                                         |
+| `outer`   | Solid border with additional space around content.       |
+| `round`   | Rounded corners.                                         |
+| `solid`   | Solid border.                                            |
+| `tall`    | Solid border with additional space top and bottom.       |
+| `vkey`    | Vertical key-line border.                                |
+| `wide`    | Solid border with additional space left and right.       |
diff --git a/docs/snippets/type_syntax/color.md b/docs/snippets/type_syntax/color.md
new file mode 100644
index 0000000000..7b87daac30
--- /dev/null
+++ b/docs/snippets/type_syntax/color.md
@@ -0,0 +1,9 @@
+The legal values for a [`<color>`](/css_types/color) depend on the [class `Color`][textual.color.Color] and include:
+
+ - a recognised [named color](../../api/color#textual.color--named-colors) (e.g., `red`);
+ - a hexadecimal number representing the RGB values of the color (e.g., `#F35573`);
+ - a color description in the RGB system (e.g., `rgb(23,78,200)`);
+ - a color description in the HSL system (e.g., `hsl(290,70%,80%)`); and
+
+For more details about the exact formats accepted, see [the class method `Color.parse`][textual.color.Color.parse].
+[Textual's default themes](../../guide/design#theme-reference) also provide many CSS variables with colors.
diff --git a/docs/snippets/type_syntax/horizontal.md b/docs/snippets/type_syntax/horizontal.md
new file mode 100644
index 0000000000..4d80d23eed
--- /dev/null
+++ b/docs/snippets/type_syntax/horizontal.md
@@ -0,0 +1,7 @@
+The [`<horizontal>`](/css_types/horizontal) type can take any of the following values:
+
+| Value            | Description                                  |
+| ---------------- | -------------------------------------------- |
+| `center`         | Aligns in the center of the horizontal axis. |
+| `left` (default) | Aligns on the left of the horizontal axis.   |
+| `right`          | Aligns on the right of the horizontal axis.  |
diff --git a/docs/snippets/type_syntax/integer.md b/docs/snippets/type_syntax/integer.md
new file mode 100644
index 0000000000..111b84b801
--- /dev/null
+++ b/docs/snippets/type_syntax/integer.md
@@ -0,0 +1 @@
+An [`<integer>`](/css_types/integer) is any valid integer number like `-10` or `42`.
diff --git a/docs/snippets/type_syntax/name.md b/docs/snippets/type_syntax/name.md
new file mode 100644
index 0000000000..b36abbb4e7
--- /dev/null
+++ b/docs/snippets/type_syntax/name.md
@@ -0,0 +1,4 @@
+A [`<name>`](/css_types/name) is any non-empty sequence of characters:
+
+ - starting with a letter `a-z`, `A-Z`, or underscore `_`; and
+ - followed by zero or more letters `a-zA-Z`, digits `0-9`, underscores `_`, and hiphens `-`.
diff --git a/docs/snippets/type_syntax/number.md b/docs/snippets/type_syntax/number.md
new file mode 100644
index 0000000000..aaf0aac070
--- /dev/null
+++ b/docs/snippets/type_syntax/number.md
@@ -0,0 +1 @@
+A [`<number>`](/css_types/number) is an [`<integer>`](/css_types/integer), optionally followed by the decimal point `.` and a decimal part composed of one or more digits.
diff --git a/docs/snippets/type_syntax/overflow.md b/docs/snippets/type_syntax/overflow.md
new file mode 100644
index 0000000000..25307f510d
--- /dev/null
+++ b/docs/snippets/type_syntax/overflow.md
@@ -0,0 +1,7 @@
+The [`<overflow>`](/css_types/overflow) type can take any of the following values:
+
+| Value    | Description                            |
+|----------|----------------------------------------|
+| `auto`   | Determine overflow mode automatically. |
+| `hidden` | Don't overflow.                        |
+| `scroll` | Allow overflowing.                     |
diff --git a/docs/snippets/type_syntax/percentage.md b/docs/snippets/type_syntax/percentage.md
new file mode 100644
index 0000000000..a131f0c2cd
--- /dev/null
+++ b/docs/snippets/type_syntax/percentage.md
@@ -0,0 +1 @@
+A [`<percentage>`](/css_types/percentage) is a [`<number>`](/css_types/number) followed by the percent sign `%` (without spaces).
diff --git a/docs/snippets/type_syntax/scalar.md b/docs/snippets/type_syntax/scalar.md
new file mode 100644
index 0000000000..f29e9f4b20
--- /dev/null
+++ b/docs/snippets/type_syntax/scalar.md
@@ -0,0 +1,8 @@
+A [`<scalar>`](/css_types/scalar) can be any of the following:
+
+ - a fixed number of cells (e.g., `10`);
+ - a fractional proportion relative to the sizes of the other widgets (e.g., `1fr`);
+ - a percentage relative to the container widget (e.g., `50%`);
+ - a percentage relative to the container width/height (e.g., `25w`/`75h`);
+ - a percentage relative to the viewport width/height (e.g., `25vw`/`75vh`); or
+ - the special value `auto` to compute the optimal size to fit without scrolling.
diff --git a/docs/snippets/type_syntax/text_align.md b/docs/snippets/type_syntax/text_align.md
new file mode 100644
index 0000000000..6720422e51
--- /dev/null
+++ b/docs/snippets/type_syntax/text_align.md
@@ -0,0 +1,14 @@
+A [`<text-align>`](/css_types/text_align) can be any of the following values:
+
+| Value     | Alignment type                       |
+|-----------|--------------------------------------|
+| `center`  | Center alignment.                    |
+| `end`     | Alias for `right`.                   |
+| `justify` | Text is justified inside the widget. |
+| `left`    | Left alignment.                      |
+| `right`   | Right alignment.                     |
+| `start`   | Alias for `left`.                    |
+
+!!! tip
+
+    The meanings of `start` and `end` will likely change when RTL languages become supported by Textual.
diff --git a/docs/snippets/type_syntax/text_style.md b/docs/snippets/type_syntax/text_style.md
new file mode 100644
index 0000000000..f95b25b9be
--- /dev/null
+++ b/docs/snippets/type_syntax/text_style.md
@@ -0,0 +1,10 @@
+A [`<text-style>`](/css_types/text_style) can be any _space-separated_ combination of the following values:
+
+| Value       | Description                                                     |
+|-------------|-----------------------------------------------------------------|
+| `bold`      | **Bold text.**                                                  |
+| `italic`    | _Italic text._                                                  |
+| `none`      | Plain text with no styling.                                     |
+| `reverse`   | Reverse video text (foreground and background colors reversed). |
+| `strike`    | 
Strikethrough text.
                                      |
+| `underline` | <u>Underline text.</u>                                          |
diff --git a/docs/snippets/type_syntax/vertical.md b/docs/snippets/type_syntax/vertical.md
new file mode 100644
index 0000000000..34e7accebb
--- /dev/null
+++ b/docs/snippets/type_syntax/vertical.md
@@ -0,0 +1,7 @@
+The [`<vertical>`](/css_types/vertical) type can take any of the following values:
+
+| Value           | Description                                |
+| --------------- | ------------------------------------------ |
+| `bottom`        | Aligns at the bottom of the vertical axis. |
+| `middle`        | Aligns in the middle of the vertical axis. |
+| `top` (default) | Aligns at the top of the vertical axis.    |
diff --git a/docs/styles/_template.md b/docs/styles/_template.md
new file mode 100644
index 0000000000..c92c701f71
--- /dev/null
+++ b/docs/styles/_template.md
@@ -0,0 +1,131 @@
+<!-- This is the template file for a CSS rule reference page. -->
+
+# Rule-name
+
+<!-- Short description of what the rule does, without syntax details or anything.
+One or two sentences is typically enough. -->
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<!--
+Formal syntax description of the rule
+rule-name: <a href="../../css_types/type_one">&lt;type-one&gt;</a>;
+-->
+--8<-- "docs/snippets/syntax_block_end.md"
+
+<!-- Description of what the rule uses the types/values for. -->
+
+### Values
+
+<!--
+If this rule only needs one type, include it directly:
+
+--8<-- "docs/snippets/type_syntax/only_type.md"
+-->
+
+<!--
+If this rule needs two or more types:
+
+### &lt;first-type&gt;
+
+--8<-- "docs/snippets/type_syntax/first_type.md"
+
+### &lt;second-type&gt;
+
+--8<-- "docs/snippets/type_syntax/second_type.md"
+
+...
+-->
+
+### Defaults
+
+<!-- If necessary, make note of the default values here.
+Otherwise, delete this section.
+E.g., `border` contains this section. -->
+
+## Examples
+
+<!--
+Short description of the first example.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/rule.py"}
+    ```
+
+=== "rule.py"
+
+    ```py
+    --8<-- "docs/examples/styles/rule.py"
+    ```
+
+=== "rule.css"
+
+    ```css
+    --8<-- "docs/examples/styles/rule.css"
+    ```
+-->
+
+<!--
+Short description of the second example.
+(If only one example is given, make sure the section is called "Example" and not "Examples".)
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/rule.py"}
+    ```
+
+=== "rule.py"
+
+    ```py
+    --8<-- "docs/examples/styles/rule.py"
+    ```
+
+=== "rule.css"
+
+    ```scss
+    --8<-- "docs/examples/styles/rule.css"
+    ```
+
+-->
+
+<!-- ... -->
+
+## CSS
+
+<!--
+The CSS syntax for the rule definitions.
+Include comments when relevant.
+Include all variations.
+List all values, if possible and sensible.
+
+```sass
+rule-name: value1
+rule-name: value2
+rule-name: different-syntax-value shown-here
+
+rule-name-variant: value3
+rule-name-variant: value4
+```
+
+-->
+
+## Python
+
+<!--
+The Python syntax for the rule definitions.
+Copy the same examples as the ones shown in the CSS above.
+
+If the programmatic way of setting the rule differs significantly from the CSS way, make note of that here.
+
+```py
+rule_name = value1
+rule_name = value2
+rule_name = (different_syntax_value, shown_here)
+
+rule_name_variant = value3
+rule_name_variant = value4
+```
+
+-->
diff --git a/docs/styles/align.md b/docs/styles/align.md
index 15bbcbed9e..0f3121f012 100644
--- a/docs/styles/align.md
+++ b/docs/styles/align.md
@@ -1,36 +1,40 @@
 # Align
 
 The `align` style aligns children within a container.
+Not to be confused with [`content-align`](../content_align).
 
 ## Syntax
 
-```
-align: <HORIZONTAL> <VERTICAL>;
-align-horizontal: <HORIZONTAL>;
-align-vertical: <VERTICAL>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+align: <a href="../../css_types/horizontal">&lt;horizontal&gt;</a> <a href="../../css_types/vertical">&lt;vertical&gt;</a>;
+
+align-horizontal: <a href="../../css_types/horizontal">&lt;horizontal&gt;</a>;
+align-vertical: <a href="../../css_types/vertical">&lt;vertical&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `align` takes a [`<horizontal>`](../../css_types/horizontal) followed by a [`<vertical>`](../../css_types/vertical).
+
+You can specify the alignment of children on both the horizontal and vertical axes at the same time,
+or on each of the axis separately.
+To specify alignment on a single axis, use the respective style and type:
 
+ - `align-horizontal` takes a [`<horizontal>`](../../css_types/horizontal) and does alignment along the horizontal axis; and
+ - `align-vertical` takes a [`<vertical>`](../../css_types/vertical) and does alignment along the vertical axis.
 
 ### Values
 
-#### `HORIZONTAL`
+#### &lt;horizontal&gt;
 
-| Value            | Description                                        |
-| ---------------- | -------------------------------------------------- |
-| `left` (default) | Align content on the left of the horizontal axis   |
-| `center`         | Align content in the center of the horizontal axis |
-| `right`          | Align content on the right of the horizontal axis  |
+--8<-- "docs/snippets/type_syntax/horizontal.md"
 
-#### `VERTICAL`
+#### &lt;vertical&gt;
 
-| Value           | Description                                      |
-| --------------- | ------------------------------------------------ |
-| `top` (default) | Align content at the top of the vertical axis    |
-| `middle`        | Align content in the middle of the vertical axis |
-| `bottom`        | Align content at the bottom of the vertical axis |
+--8<-- "docs/snippets/type_syntax/vertical.md"
 
 
-## Example
+## Examples
+
+This example contains a simple app with two labels centered on the screen with `align: center middle;`:
 
 === "align.py"
 
@@ -50,13 +54,38 @@ align-vertical: <VERTICAL>;
 
     ```
 
+The next example shows a 3 by 3 grid of containers with text labels.
+Each label has been aligned differently inside its container, and its text shows its `align: ...` value.
+
+=== "align_all.py"
+
+    ```python
+    --8<-- "docs/examples/styles/align_all.py"
+    ```
+
+=== "align_all.css"
+
+    ```css
+    --8<-- "docs/examples/styles/align_all.css"
+    ```
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/align_all.py"}
+    ```
+
 ## CSS
 
 ```sass
 /* Align child widgets to the center. */
 align: center middle;
-/* Align child widget to th top right */
+/* Align child widget to the top right */
 align: right top;
+
+/* Change the horizontal alignment of the children of a widget */
+align-horizontal: right;
+/* Change the vertical alignment of the children of a widget */
+align-vertical: middle;
 ```
 
 ## Python
@@ -65,4 +94,9 @@ align: right top;
 widget.styles.align = ("center", "middle")
 # Align child widgets to the top right
 widget.styles.align = ("right", "top")
+
+# Change the horizontal alignment of the children of a widget
+widget.styles.align_horizontal = "right"
+# Change the vertical alignment of the children of a widget
+widget.styles.align_vertical = "middle"
 ```
diff --git a/docs/styles/background.md b/docs/styles/background.md
index 6c41885c77..d22581a576 100644
--- a/docs/styles/background.md
+++ b/docs/styles/background.md
@@ -1,14 +1,27 @@
 # Background
 
-The `background` rule sets the background color of the widget.
+The `background` rule sets the background color of a widget.
 
 ## Syntax
 
-```
-background: <COLOR> [<PERCENTAGE>];
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+background: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `background` needs a [`<color>`](../../css_types/color) followed by an optional [`<percentage>`](../../css_types/percentage) to specify the color transparency.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
 
-## Example
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+This is clamped between `0%` and `100%`.
+
+## Examples
 
 This example creates three widgets and applies a different background to each.
 
@@ -29,6 +42,25 @@ This example creates three widgets and applies a different background to each.
     ```{.textual path="docs/examples/styles/background.py"}
     ```
 
+The next example creates ten widgets layed out side by side to show the effect of setting different percentages for the transparency of the background color.
+
+=== "background_transparency.py"
+
+    ```python
+    --8<-- "docs/examples/styles/background_transparency.py"
+    ```
+
+=== "background_transparency.css"
+
+    ```sass
+    --8<-- "docs/examples/styles/background_transparency.css"
+    ```
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/background_transparency.py"}
+    ```
+
 ## CSS
 
 ```sass
@@ -40,6 +72,9 @@ background: red 20%;
 
 /* RGB color */
 background: rgb(100,120,200);
+
+/* HSL color */
+background: hsl(290,70%,80%);
 ```
 
 ## Python
@@ -49,9 +84,13 @@ You can use the same syntax as CSS, or explicitly set a `Color` object for finer
 ```python
 # Set blue background
 widget.styles.background = "blue"
+# Set through HSL model
+widget.styles.background = "hsl(351,32%,89%)"
 
 from textual.color import Color
-# Set with a color object
+# Set with a color object by parsing a string
 widget.styles.background = Color.parse("pink")
+widget.styles.background = Color.parse("#FF00FF")
+# Set with a color object instantiated directly
 widget.styles.background = Color(120, 60, 100)
 ```
diff --git a/docs/styles/border.md b/docs/styles/border.md
index 757ce988bb..15013f650f 100644
--- a/docs/styles/border.md
+++ b/docs/styles/border.md
@@ -1,50 +1,64 @@
 # Border
 
-The `border` rule enables the drawing of a box around a widget. A border is set with a border value (see below) followed by a color.
+The `border` rule enables the drawing of a box around a widget.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+border: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+
+border-top: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+border-right: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+border-bottom: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+border-left: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `border` accepts an optional [`<border>`](../../css_types/border) that sets the visual style of the widget border and an optional [`<color>`](../../css_types/color) to set the color of the border.
 
 Borders may also be set individually for the four edges of a widget with the `border-top`, `border-right`, `border-bottom` and `border-left` rules.
 
-## Syntax
+### Values
 
-```
-border: [<COLOR>] [<BORDER VALUE>];
-border-top: [<COLOR>] [<BORDER VALUE>];
-border-right: [<COLOR>] [<BORDER VALUE>];
-border-bottom: [<COLOR>] [<BORDER VALUE>];
-border-left: [<COLOR>] [<BORDER VALUE>];
+#### &lt;border&gt;
+
+--8<-- "docs/snippets/type_syntax/border.md"
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+### Multiple edge rules
+
+If multiple border rules target the same edge, the last rule that targets a specific edge is the one that is applied to that edge.
+For example, consider the CSS below:
+
+```sass
+Static {
+    border-top: dashed red;
+    border: solid green;  /* overrides the border-top rule above */
+    /* Change the border but just for the bottom edge: */
+    border-bottom: double blue;
+}
 ```
 
-### Values
+The CSS snippet above will add a solid green border around `Static` widgets, except for the bottom edge, which will be double blue.
+
+### Defaults
 
-| Border value | Description                                             |
-|--------------|---------------------------------------------------------|
-| `"ascii"`    | A border with plus, hyphen, and vertical bar            |
-| `"blank"`    | A blank border (reserves space for a border)            |
-| `"dashed"`   | Dashed line border                                      |
-| `"double"`   | Double lined border                                     |
-| `"heavy"`    | Heavy border                                            |
-| `"hidden"`   | Alias for "none"                                        |
-| `"hkey"`     | Horizontal key-line border                              |
-| `"inner"`    | Thick solid border                                      |
-| `"none"`     | Disabled border                                         |
-| `"outer"`    | Think solid border with additional space around content |
-| `"round"`    | Rounded corners                                         |
-| `"solid"`    | Solid border                                            |
-| `"tall"`     | Solid border with extras space top and bottom           |
-| `"vkey"`     | Vertical key-line border                                |
-| `"wide"`     | Solid border with additional space left and right       |
-
-For example, `heavy white` would display a heavy white line around a widget.
+If `<color>` is specified but `<border>` is not, it defaults to `"solid"`.
+If `<border>` is specified but `<color>`is not, it defaults to green (RGB color `"#00FF00"`).
 
 ## Border command
 
-The `textual` CLI has a subcommand which will let you explore the various border types:
+The `textual` CLI has a subcommand which will let you explore the various border types interactively:
 
 ```
 textual borders
 ```
 
-## Example
+Alternatively, you can see the examples below.
+
+## Examples
 
 This examples shows three widgets with different border styles.
 
@@ -65,6 +79,25 @@ This examples shows three widgets with different border styles.
     ```{.textual path="docs/examples/styles/border.py"}
     ```
 
+The next example shows a grid with all the available border types.
+
+=== "border_all.py"
+
+    ```py
+    --8<-- "docs/examples/styles/border_all.py"
+    ```
+
+=== "border_all.css"
+
+    ```css
+    --8<-- "docs/examples/styles/border_all.css"
+    ```
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/border_all.py"}
+    ```
+
 ## CSS
 
 ```sass
diff --git a/docs/styles/box_sizing.md b/docs/styles/box_sizing.md
index bc089ad443..5ad0be42af 100644
--- a/docs/styles/box_sizing.md
+++ b/docs/styles/box_sizing.md
@@ -5,12 +5,12 @@ The `box-sizing` property determines how the width and height of a widget are ca
 ## Syntax
 
 ```
-box-sizing: [border-box|content-box];
+box-sizing: border-box | content-box;
 ```
 
 ### Values
 
-| Values                 | Description                                                                                                                                                             |
+| Value                  | Description                                                                                                                                                             |
 |------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
 | `border-box` (default) | Padding and border are included in the width and height. If you add padding and/or border the widget will not change in size, but you will have less space for content. |
 | `content-box`          | Padding and border will increase the size of the widget, leaving the content area unaffected.                                                                           |
@@ -18,7 +18,7 @@ box-sizing: [border-box|content-box];
 ## Example
 
 Both widgets in this example have the same height (5).
-The top widget has `box-sizing: border-box` which means that padding and border reduces the space for content.
+The top widget has `box-sizing: border-box` which means that padding and border reduce the space for content.
 The bottom widget has `box-sizing: content-box` which increases the size of the widget to compensate for padding and border.
 
 === "box_sizing.py"
diff --git a/docs/styles/color.md b/docs/styles/color.md
index 0fae0a0b0f..4db2eccb4b 100644
--- a/docs/styles/color.md
+++ b/docs/styles/color.md
@@ -1,16 +1,32 @@
 # Color
 
-The `color` rule sets the text color of a Widget.
+The `color` rule sets the text color of a widget.
 
 ## Syntax
 
-```
-color: <COLOR> | auto [<PERCENTAGE>];
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+color: (<a href="../../css_types/color">&lt;color&gt;</a> | auto) [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `color` needs a [`<color>`](../../css_types/color) followed by an optional [`<percentage>`](../../css_types/percentage) to specify the color transparency.
+
+Instead of a [`<color>`](../../css_types/color), one can use the special value `"auto"` to choose automatically the color with the best contrast for readability purposes.
+
+### Values
+
+#### &lt;color&gt;
 
-## Example
+--8<-- "docs/snippets/type_syntax/color.md"
 
-This example sets a different text color to three different widgets.
+The alternative value `"auto"` picks the color that provides the best contrast for readability purposes.
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Examples
+
+This example sets a different text color for each of three different widgets.
 
 === "color.py"
 
@@ -29,6 +45,25 @@ This example sets a different text color to three different widgets.
     ```{.textual path="docs/examples/styles/color.py"}
     ```
 
+The next example shows how `auto` chooses between a lighter or a darker text color to increase the contrast and improve readability.
+
+=== "color_auto.py"
+
+    ```py
+    --8<-- "docs/examples/styles/color_auto.py"
+    ```
+
+=== "color_auto.css"
+
+    ```css hl_lines="2"
+    --8<-- "docs/examples/styles/color_auto.css"
+    ```
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/color_auto.py"}
+    ```
+
 ## CSS
 
 ```sass
@@ -56,5 +91,4 @@ widget.styles.color = "blue"
 from textual.color import Color
 # Set with a color object
 widget.styles.color = Color.parse("pink")
-
 ```
diff --git a/docs/styles/content_align.md b/docs/styles/content_align.md
index 35a4a4c57c..bdf0731997 100644
--- a/docs/styles/content_align.md
+++ b/docs/styles/content_align.md
@@ -1,34 +1,40 @@
 # Content-align
 
 The `content-align` style aligns content _inside_ a widget.
+Not to be confused with [`align`](../align).
 
-You can specify the alignment of content on both the horizontal and vertical axes.
 
 ## Syntax
 
-```
-content-align: <HORIZONTAL> <VERTICAL>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+content-align: <a href="../../css_types/horizontal">&lt;horizontal&gt;</a> <a href="../../css_types/vertical">&lt;vertical&gt;</a>;
+
+content-align-horizontal: <a href="../../css_types/horizontal">&lt;horizontal&gt;</a>;
+content-align-vertical: <a href="../../css_types/vertical">&lt;vertical&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `content-align` takes a [`<horizontal>`](../../css_types/horizontal) followed by a [`<vertical>`](../../css_types/vertical).
+
+You can specify the alignment of content on both the horizontal and vertical axes at the same time,
+or on each of the axis separately.
+To specify content alignment on a single axis, use the respective style and type:
+
+ - `content-align-horizontal` takes a [`<horizontal>`](../../css_types/horizontal) and does alignment along the horizontal axis; and
+ - `content-align-vertical` takes a [`<vertical>`](../../css_types/vertical) and does alignment along the vertical axis.
 
 ### Values
 
-#### `HORIZONTAL`
+#### &lt;horizontal&gt;
+
+--8<-- "docs/snippets/type_syntax/horizontal.md"
 
-| Value            | Description                                        |
-| ---------------- | -------------------------------------------------- |
-| `left` (default) | Align content on the left of the horizontal axis   |
-| `center`         | Align content in the center of the horizontal axis |
-| `right`          | Align content on the right of the horizontal axis  |
+#### &lt;vertical&gt;
 
-#### `VERTICAL`
+--8<-- "docs/snippets/type_syntax/vertical.md"
 
-| Value           | Description                                      |
-| --------------- | ------------------------------------------------ |
-| `top` (default) | Align content at the top of the vertical axis    |
-| `middle`        | Align content in the middle of the vertical axis |
-| `bottom`        | Align content at the bottom of the vertical axis |
+## Examples
 
-## Example
+This first example shows three labels stacked vertically, each with different content alignments.
 
 === "content_align.py"
 
@@ -38,7 +44,7 @@ content-align: <HORIZONTAL> <VERTICAL>;
 
 === "content_align.css"
 
-    ```scss
+    ```scss hl_lines="2 7-8 13"
     --8<-- "docs/examples/styles/content_align.css"
     ```
 
@@ -47,6 +53,26 @@ content-align: <HORIZONTAL> <VERTICAL>;
     ```{.textual path="docs/examples/styles/content_align.py"}
     ```
 
+The next example shows a 3 by 3 grid of labels.
+Each label has its text aligned differently.
+
+=== "content_align_all.py"
+
+    ```py
+    --8<-- "docs/examples/styles/content_align_all.py"
+    ```
+
+=== "content_align_all.css"
+
+    ```css
+    --8<-- "docs/examples/styles/content_align_all.css"
+    ```
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/content_align_all.py"}
+    ```
+
 ## CSS
 
 ```sass
@@ -54,6 +80,11 @@ content-align: <HORIZONTAL> <VERTICAL>;
 content-align: center middle;
 /* Align content at the top right of a widget */
 content-align: right top;
+
+/* Change the horizontal alignment of the content of a widget */
+content-align-horizontal: right;
+/* Change the vertical alignment of the content of a widget */
+content-align-vertical: middle;
 ```
 
 ## Python
@@ -62,4 +93,9 @@ content-align: right top;
 widget.styles.content_align = ("center", "middle")
 # Align content at the top right of a widget
 widget.styles.content_align = ("right", "top")
+
+# Change the horizontal alignment of the content of a widget
+widget.styles.content_align_horizontal = "right"
+# Change the vertical alignment of the content of a widget
+widget.styles.content_align_vertical = "middle"
 ```
diff --git a/docs/styles/display.md b/docs/styles/display.md
index 5462367d49..c9a52f3297 100644
--- a/docs/styles/display.md
+++ b/docs/styles/display.md
@@ -5,19 +5,19 @@ The `display` property defines whether a widget is displayed or not.
 ## Syntax
 
 ```
-display: [none|block];
+display: block | none;
 ```
 
 ### Values
 
-| Value             | Description                                                               |
-|-------------------|---------------------------------------------------------------------------|
-| `block` (default) | Display the widget as normal                                              |
-| `none`            | The widget not be displayed, and space will no longer be reserved for it. |
+| Value             | Description                                                              |
+|-------------------|--------------------------------------------------------------------------|
+| `block` (default) | Display the widget as normal.                                            |
+| `none`            | The widget is not displayed and space will no longer be reserved for it. |
 
 ## Example
 
-Note that the second widget is hidden by adding the `"remove"` class which sets the display style to None.
+Note that the second widget is hidden by adding the `"remove"` class which sets the display style to `none`.
 
 === "display.py"
 
@@ -39,10 +39,10 @@ Note that the second widget is hidden by adding the `"remove"` class which sets
 ## CSS
 
 ```sass
-/* Widget is on screen */
+/* Widget is shown */
 display: block;
 
-/* Widget is not on the screen */
+/* Widget is not shown */
 display: none;
 ```
 
diff --git a/docs/styles/dock.md b/docs/styles/dock.md
index 8753586142..dceb0beec8 100644
--- a/docs/styles/dock.md
+++ b/docs/styles/dock.md
@@ -5,10 +5,12 @@ The `dock` property is used to fix a widget to the edge of a container (which ma
 ## Syntax
 
 ```
-dock: top|right|bottom|left;
+dock: bottom | left | right | top;
 ```
 
-## Example
+The option chosen determines the edge to which the widget is docked.
+
+## Examples
 
 The example below shows a `left` docked sidebar.
 Notice that even though the content is scrolled, the sidebar remains fixed.
@@ -30,16 +32,40 @@ Notice that even though the content is scrolled, the sidebar remains fixed.
     --8<-- "docs/examples/guide/layout/dock_layout1_sidebar.css"
     ```
 
+The second example shows how one can use full-width or full-height containers to dock labels to the edges of a larger container.
+The labels will remain in that position (docked) even if the container they are in scrolls horizontally and/or vertically.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/dock_all.py"}
+    ```
+
+=== "dock_all.py"
+
+    ```py
+    --8<-- "docs/examples/styles/dock_all.py"
+    ```
+
+=== "dock_all.css"
+
+    ```css hl_lines="2-5 8-11 14-17 20-23"
+    --8<-- "docs/examples/styles/dock_all.css"
+    ```
+
 ## CSS
 
 ```sass
-/* Dock the widget on the left edge of its parent container */
-dock: left;
+dock: bottom;  /* Docks on the bottom edge of the parent container. */
+dock: left;    /* Docks on the   left edge of the parent container. */
+dock: right;   /* Docks on the  right edge of the parent container. */
+dock: top;     /* Docks on the    top edge of the parent container. */
 ```
 
 ## Python
 
 ```python
-# Dock the widget on the left edge of its parent container
-widget.styles.dock = "left"
+widget.styles.dock = bottom;  # Dock bottom.
+widget.styles.dock = left;    # Dock   left.
+widget.styles.dock = right;   # Dock  right.
+widget.styles.dock = top;     # Dock    top.
 ```
diff --git a/docs/styles/grid.md b/docs/styles/grid.md
deleted file mode 100644
index 9f7bbc1fdb..0000000000
--- a/docs/styles/grid.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# Grid
-
-There are a number of properties relating to the Textual `grid` layout.
-
-For an in-depth look at the grid layout, visit the grid [guide](../guide/layout.md#grid).
-
-| Property       | Description                                    |
-|----------------|------------------------------------------------|
-| `grid-size`    | Number of columns and rows in the grid layout. |
-| `grid-rows`    | Height of grid rows.                           |
-| `grid-columns` | Width of grid columns.                         |
-| `grid-gutter`  | Spacing between grid cells.                    |
-| `row-span`     | Number of rows a cell spans.                   |
-| `column-span`  | Number of columns a cell spans.                |
-
-## Syntax
-
-```sass
-grid-size: <INTEGER> [<INTEGER>];
-/* columns first, then rows */
-grid-rows: <SCALAR> . . .;
-grid-columns: <SCALAR> . . .;
-grid-gutter: <SCALAR>;
-row-span: <INTEGER>;
-column-span: <INTEGER>;
-```
-
-## Example
-
-The example below shows all the properties above in action.
-The `grid-size: 3 4;` declaration sets the grid to 3 columns and 4 rows.
-The first cell of the grid, tinted magenta, shows a cell spanning multiple rows and columns.
-The spacing between grid cells is because of the `grid-gutter` declaration.
-
-=== "Output"
-
-    ```{.textual path="docs/examples/styles/grid.py"}
-    ```
-
-=== "grid.py"
-
-    ```python
-    --8<-- "docs/examples/styles/grid.py"
-    ```
-
-=== "grid.css"
-
-    ```sass
-    --8<-- "docs/examples/styles/grid.css"
-    ```
-
-!!! warning
-
-    The properties listed on this page will only work when the layout is `grid`.
diff --git a/docs/styles/grid/column_span.md b/docs/styles/grid/column_span.md
new file mode 100644
index 0000000000..7f02b87d4e
--- /dev/null
+++ b/docs/styles/grid/column_span.md
@@ -0,0 +1,52 @@
+# Column-span
+
+The `column-span` style specifies how many rows a widget will span in a grid layout.
+
+!!! note
+
+    This style only affects widgets that are direct children of a widget with `layout: grid`.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+column-span: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `column-span` accepts a single non-negative [`<integer>`](../../../css_types/integer) that quantifies how many columns the given widget spans.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/integer.md"
+
+## Example
+
+The example below shows a 4 by 4 grid where many placeholders span over several columns.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/column_span.py"}
+    ```
+
+=== "column_span.py"
+
+    ```py
+    --8<-- "docs/examples/styles/column_span.py"
+    ```
+
+=== "column_span.css"
+
+    ```css
+    --8<-- "docs/examples/styles/column_span.css"
+    ```
+
+## CSS
+
+```sass
+column-span: 3
+```
+
+## Python
+
+```py
+widget.styles.column_span = 3
+```
diff --git a/docs/styles/grid/grid_columns.md b/docs/styles/grid/grid_columns.md
new file mode 100644
index 0000000000..f603fde860
--- /dev/null
+++ b/docs/styles/grid/grid_columns.md
@@ -0,0 +1,68 @@
+# Grid-columns
+
+The `grid-columns` style allows to define the width of the columns of the grid.
+
+!!! note
+
+    This style only affects widgets with `layout: grid`.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+grid-columns: <a href="../../css_types/scalar">&lt;scalar&gt;</a>+;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `grid-columns` takes one or more [`<scalar>`](../../../css_types/scalar) that specify the length of the columns of the grid.
+
+If there are more columns in the grid than scalars specified in `grid-columns`, they are reused cyclically.
+If the number of [`<scalar>`](../../../css_types/scalar) is in excess, the excess is ignored.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
+
+## Example
+
+The example below shows a grid with 10 labels laid out in a grid with 2 rows and 5 columns.
+
+We set `grid-columns: 1fr 16 2fr`.
+Because there are more rows than scalars in the style rule, the scalars will be reused:
+
+ - columns 1 and 4 have width `1fr`;
+ - columns 2 and 5 have width `16`; and
+ - column 3 has width `2fr`.
+
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/grid_columns.py"}
+    ```
+
+=== "grid_columns.py"
+
+    ```py
+    --8<-- "docs/examples/styles/grid_columns.py"
+    ```
+
+=== "grid_columns.css"
+
+    ```css
+    --8<-- "docs/examples/styles/grid_columns.css"
+    ```
+
+## CSS
+
+```sass
+/* Set all columns to have 50% width */
+grid-columns: 50%;
+
+/* Every other column is twice as wide as the first one */
+grid-columns: 1fr 2fr;
+```
+
+### Python
+
+```py
+grid.styles.grid_columns = "50%"
+grid.styles.grid_columns = "1fr 2fr"
+```
diff --git a/docs/styles/grid/grid_gutter.md b/docs/styles/grid/grid_gutter.md
new file mode 100644
index 0000000000..2488f95f0c
--- /dev/null
+++ b/docs/styles/grid/grid_gutter.md
@@ -0,0 +1,67 @@
+# Grid-gutter
+
+The `grid-gutter` style sets the size of the gutter in the grid layout.
+That is, it sets the space between adjacent cells in the grid.
+
+Gutter is only applied _between_ the edges of cells.
+No spacing is added between the edges of cells and the edges of the container.
+
+!!! note
+
+    This style only affects widgets with `layout: grid`.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+grid-gutter: <a href="../../css_types/scalar">&lt;scalar&gt;</a> [<a href="../../css_types/scalar">&lt;scalar&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `grid-gutter` takes one or two [`<scalar>`](../../../css_types/scalar) that set the length of the gutter along the vertical and horizontal axes.
+If only one [`<scalar>`](../../../css_types/scalar) is supplied, it sets the vertical and horizontal gutters.
+If two are supplied, they set the vertical and horizontal gutters, respectively.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
+
+## Example
+
+The example below employs a common trick to apply visually consistent spacing around all grid cells.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/grid_gutter.py"}
+    ```
+
+=== "grid_gutter.py"
+
+    ```py
+    --8<-- "docs/examples/styles/grid_gutter.py"
+    ```
+
+=== "grid_gutter.css"
+
+    ```css
+    --8<-- "docs/examples/styles/grid_gutter.css"
+    ```
+
+    1. We set the horizontal gutter to be double the vertical gutter because terminal cells are typically two times taller than they are wide. Thus, the result shows visually consistent spacing around grid cells.
+
+## CSS
+
+```sass
+/* Set vertical and horizontal gutters to be the same */
+grid-gutter: 5%;
+
+/* Set vertical and horizontal gutters separately */
+grid-gutter: 1 2;
+```
+
+## Python
+
+Vertical and horizontal gutters correspond to different Python properties, so they must be set separately:
+
+```py
+widget.styles.grid_gutter_vertical = "1"
+widget.styles.grid_gutter_horizontal = "2"
+```
diff --git a/docs/styles/grid/grid_rows.md b/docs/styles/grid/grid_rows.md
new file mode 100644
index 0000000000..72b12b2701
--- /dev/null
+++ b/docs/styles/grid/grid_rows.md
@@ -0,0 +1,68 @@
+# Grid-rows
+
+The `grid-rows` style allows to define the height of the rows of the grid.
+
+!!! note
+
+    This style only affects widgets with `layout: grid`.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+grid-rows: <a href="../../css_types/scalar">&lt;scalar&gt;</a>+;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `grid-rows` takes one or more [`<scalar>`](../../../css_types/scalar) that specify the length of the rows of the grid.
+
+If there are more rows in the grid than scalars specified in `grid-rows`, they are reused cyclically.
+If the number of [`<scalar>`](../../../css_types/scalar) is in excess, the excess is ignored.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
+
+## Example
+
+The example below shows a grid with 10 labels laid out in a grid with 5 rows and 2 columns.
+
+We set `grid-rows: 1fr 6 25%`.
+Because there are more rows than scalars in the style rule, the scalars will be reused:
+
+ - rows 1 and 4 have height `1fr`;
+ - rows 2 and 5 have height `6`; and
+ - row 3 has height `25%`.
+
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/grid_rows.py"}
+    ```
+
+=== "grid_rows.py"
+
+    ```py
+    --8<-- "docs/examples/styles/grid_rows.py"
+    ```
+
+=== "grid_rows.css"
+
+    ```css
+    --8<-- "docs/examples/styles/grid_rows.css"
+    ```
+
+## CSS
+
+```sass
+/* Set all rows to have 50% height */
+grid-rows: 50%;
+
+/* Every other row is twice as tall as the first one */
+grid-rows: 1fr 2fr;
+```
+
+### Python
+
+```py
+grid.styles.grid_rows = "50%"
+grid.styles.grid_rows = "1fr 2fr"
+```
diff --git a/docs/styles/grid/grid_size.md b/docs/styles/grid/grid_size.md
new file mode 100644
index 0000000000..b35e4d3914
--- /dev/null
+++ b/docs/styles/grid/grid_size.md
@@ -0,0 +1,86 @@
+# Grid-size
+
+The `grid-size` style sets the number of columns and rows in a grid layout.
+
+The number of rows can be left unspecified and it will be computed automatically.
+
+!!! note
+
+    This style only affects widgets with `layout: grid`.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+grid-size: <a href="../../css_types/integer">&lt;integer&gt;</a> [<a href="../../css_types/integer">&lt;integer&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `grid-size` takes one or two non-negative [`<integer>`](../../../css_types/integer).
+The first defines how many columns there are in the grid.
+If present, the second one sets the number of rows – regardless of the number of children of the grid –, otherwise the number of rows is computed automatically.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/integer.md"
+
+## Examples
+
+In the first example, we create a grid with 2 columns and 5 rows, regardless of the fact that we do not have enough labels to fill in the whole grid:
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/grid_size_both.py"}
+    ```
+
+=== "grid_size_both.py"
+
+    ```py
+    --8<-- "docs/examples/styles/grid_size_both.py"
+    ```
+
+=== "grid_size_both.css"
+
+    ```css hl_lines="2"
+    --8<-- "docs/examples/styles/grid_size_both.css"
+    ```
+
+    1. Create a grid with 2 columns and 4 rows.
+
+In the second example, we create a grid with 2 columns and however many rows are needed to display all of the grid children:
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/grid_size_columns.py"}
+    ```
+
+=== "grid_size_columns.py"
+
+    ```py
+    --8<-- "docs/examples/styles/grid_size_columns.py"
+    ```
+
+=== "grid_size_columns.css"
+
+    ```css
+    --8<-- "docs/examples/styles/grid_size_columns.css"
+    ```
+
+    1. Create a grid with 2 columns and however many rows.
+
+## CSS
+
+```sass
+/* Grid with 3 rows and 5 columns */
+grid-size: 3 5;
+
+/* Grid with 4 columns and as many rows as needed */
+grid-size: 4;
+```
+
+## Python
+
+To programmatically change the grid size, the number of rows and columns must be specified separately:
+
+```py
+widget.styles.grid_size_rows = 3
+widget.styles.grid_size_columns = 6
+```
diff --git a/docs/styles/grid/index.md b/docs/styles/grid/index.md
new file mode 100644
index 0000000000..b96f1fbd5f
--- /dev/null
+++ b/docs/styles/grid/index.md
@@ -0,0 +1,71 @@
+# Grid
+
+There are a number of properties relating to the Textual `grid` layout.
+
+For an in-depth look at the grid layout, visit the grid [guide](../guide/layout.md#grid).
+
+| Property       | Description                                    |
+|----------------|------------------------------------------------|
+| [`column-span`](./column_span.md)  | Number of columns a cell spans.                |
+| [`grid-columns`](./grid_columns.md) | Width of grid columns.                         |
+| [`grid-gutter`](./grid_gutter.md)  | Spacing between grid cells.                    |
+| [`grid-rows`](./grid_rows.md)    | Height of grid rows.                           |
+| [`grid-size`](./grid_size.md)    | Number of columns and rows in the grid layout. |
+| [`row-span`](./row_span.md)     | Number of rows a cell spans.                   |
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./column_span.md">column-span</a>: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+
+<a href="./grid_columns.md">grid-columns</a>: <a href="../../css_types/scalar">&lt;scalar&gt;</a>+;
+
+<a href="./grid_gutter.md">grid-gutter</a>: <a href="../../css_types/scalar">&lt;scalar&gt;</a> [<a href="../../css_types/scalar">&lt;scalar&gt;</a>];
+
+<a href="./grid_rows.md">grid-rows</a>: <a href="../../css_types/scalar">&lt;scalar&gt;</a>+;
+
+<a href="./grid_size.md">grid-size</a>: <a href="../../css_types/integer">&lt;integer&gt;</a> [<a href="../../css_types/integer">&lt;integer&gt;</a>];
+
+<a href="./row_span.md">row-span</a>: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+Visit each style's reference page to learn more about how the values are used.
+
+
+### Values
+
+#### &lt;integer&gt;
+
+--8<-- "docs/snippets/type_syntax/integer.md"
+
+#### &lt;scalar&gt;
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
+
+## Example
+
+The example below shows all the properties above in action.
+The `grid-size: 3 4;` declaration sets the grid to 3 columns and 4 rows.
+The first cell of the grid, tinted magenta, shows a cell spanning multiple rows and columns.
+The spacing between grid cells is because of the `grid-gutter` declaration.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/grid.py"}
+    ```
+
+=== "grid.py"
+
+    ```python
+    --8<-- "docs/examples/styles/grid.py"
+    ```
+
+=== "grid.css"
+
+    ```sass
+    --8<-- "docs/examples/styles/grid.css"
+    ```
+
+!!! warning
+
+    The properties listed on this page will only work when the layout is `grid`.
diff --git a/docs/styles/grid/row_span.md b/docs/styles/grid/row_span.md
new file mode 100644
index 0000000000..8e874480b4
--- /dev/null
+++ b/docs/styles/grid/row_span.md
@@ -0,0 +1,55 @@
+# Row-span
+
+The `row-span` style specifies how many rows a widget will span in a grid layout.
+
+!!! note
+
+    This style only affects widgets that are direct children of a widget with `layout: grid`.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+row-span: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `row-span` accepts a single non-negative [`<integer>`](../../../css_types/integer) that quantifies how many rows the given widget spans.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/integer.md"
+
+## Example
+
+The example below shows a 4 by 4 grid where many placeholders span over several rows.
+
+Notice that grid cells are filled from left to right, top to bottom.
+After placing the placeholders `#p1`, `#p2`, `#p3`, and `#p4`, the next available cell is in the second row, fourth column, which is where the top of `#p5` is.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/row_span.py"}
+    ```
+
+=== "row_span.py"
+
+    ```py
+    --8<-- "docs/examples/styles/row_span.py"
+    ```
+
+=== "row_span.css"
+
+    ```css
+    --8<-- "docs/examples/styles/row_span.css"
+    ```
+
+## CSS
+
+```sass
+row-span: 3
+```
+
+## Python
+
+```py
+widget.styles.row_span = 3
+```
diff --git a/docs/styles/height.md b/docs/styles/height.md
index 18622615d8..a4858a95f8 100644
--- a/docs/styles/height.md
+++ b/docs/styles/height.md
@@ -1,14 +1,21 @@
 # Height
 
-The `height` rule sets a widget's height. By default, it sets the height of the content area, but if `box-sizing` is set to `border-box` it sets the height of the border area.
+The `height` rule sets a widget's height.
 
 ## Syntax
 
-```
-height: <SCALAR>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+height: <a href="../../css_types/scalar">&lt;scalar&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `height` needs a [`<scalar>`](../../css_types/scalar) to determine the vertical length of the widget.
+By default, it sets the height of the content area, but if [`box-sizing`](./box_sizing) is set to `border-box` it sets the height of the border area.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
 
-## Example
+## Examples
 
 This examples creates a widget with a height of 50% of the screen.
 
@@ -29,6 +36,41 @@ This examples creates a widget with a height of 50% of the screen.
     ```{.textual path="docs/examples/styles/height.py"}
     ```
 
+The next example creates a series of wide widgets with heights set with different units.
+Open the CSS file tab to see the comments that explain how each height is computed.
+(The output includes a vertical ruler on the right to make it easier to check the height of each widget.)
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/height_comparison.py" lines=24 columns=80}
+    ```
+
+=== "height_comparison.py"
+
+    ```py hl_lines="15-23"
+    --8<-- "docs/examples/styles/height_comparison.py"
+    ```
+
+    1. The id of the placeholder identifies which unit will be used to set the height of the widget.
+
+=== "height_comparison.css"
+
+    ```css hl_lines="2 5 8 11 14 17 20 23 26"
+    --8<-- "docs/examples/styles/height_comparison.css"
+    ```
+
+    1. This sets the height to 2 lines.
+    2. This sets the height to 12.5% of the space made available by the container. The container is 24 lines tall, so 12.5% of 24 is 3.
+    3. This sets the height to 5% of the width of the direct container, which is the `Vertical` container. Because it expands to fit all of the terminal, the width of the `Vertical` is 80 and 5% of 80 is 4.
+    4. This sets the height to 12.5% of the height of the direct container, which is the `Vertical` container. Because it expands to fit all of the terminal, the height of the `Vertical` is 24 and 12.5% of 24 is 3.
+    5. This sets the height to 7.5% of the viewport width, which is 80. 7.5% of 80 is 5.6 which gets truncated to 5.
+    6. This sets the height to 12.5% of the viewport height, which is 24. 12.5% of 24 is 3.
+    7. This sets the height of the placeholder to be the optimal size that fits the content without scrolling.
+    Because the content only spans one line, the placeholder has its height set to 1.
+    8. This sets the height to `1fr`, which means this placeholder will have half the height of a placeholder with `2fr`.
+    9. This sets the height to `2fr`, which means this placeholder will have twice the height of a placeholder with `1fr`.
+
+
 ## CSS
 
 ```sass
@@ -45,7 +87,7 @@ height: auto
 ## Python
 
 ```python
-self.styles.height = 10
+self.styles.height = 10  # Explicit cell height can be an int
 self.styles.height = "50%"
 self.styles.height = "auto"
 ```
diff --git a/docs/styles/layer.md b/docs/styles/layer.md
index 383e745b26..6e6f024768 100644
--- a/docs/styles/layer.md
+++ b/docs/styles/layer.md
@@ -1,15 +1,25 @@
 # Layer
 
-The `layer` property is used to assign widgets to a layer.
-The value of the `layer` property must be the name of a layer defined using a `layers` declaration.
-Layers control the order in which widgets are painted on screen.
-More information on layers can be found in the [guide](../guide/layout.md#layers).
+The `layer` property defines the layer a widget belongs to.
 
 ## Syntax
 
-```
-layer: <STRING>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+layer: <a href="../../css_types/name">&lt;name&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The `layer` rule accepts a [`<name>`](../../css_types/name) that defines the layer this widget belongs to.
+This [`<name>`](../../css_types/name) must correspond to a [`<name>`](../../css_types/name) that has been defined in a [`layers`](./layers) rule by an ancestor of this widget.
+
+More information on layers can be found in the [guide](../guide/layout.md#layers).
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/name.md"
+
+!!! warning
+
+    Using a `<name>` that hasn't been defined in a [`layers`](./layers.md) declaration of an ancestor of this widget has no effect.
 
 ## Example
 
@@ -31,7 +41,7 @@ However, since `#box1` is on the higher layer, it is drawn on top of `#box2`.
 
 === "layers.css"
 
-    ```sass hl_lines="3 15 19"
+    ```sass hl_lines="3 14 19"
     --8<-- "docs/examples/guide/layout/layers.css"
     ```
 
@@ -46,5 +56,5 @@ layer: below;
 
 ```python
 # Draw the widget on the layer called 'below'
-widget.layer = "below"
+widget.styles.layer = "below"
 ```
diff --git a/docs/styles/layers.md b/docs/styles/layers.md
index 9eed3156dd..427d2761ee 100644
--- a/docs/styles/layers.md
+++ b/docs/styles/layers.md
@@ -1,15 +1,23 @@
 # Layers
 
 The `layers` property allows you to define an ordered set of layers.
-These `layers` can later be referenced using the `layer` property.
-Layers control the order in which widgets are painted on screen.
-More information on layers can be found in the [guide](../guide/layout.md#layers).
 
 ## Syntax
 
-```
-layers: <STRING> ...;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+layers: <a href="../../css_types/name">&lt;name&gt;</a>+;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The `layers` rule accepts one or more [`<name>`](../../css_types/name) that define the layers that the widget is aware of, and the order in which they will be painted on the screen.
+
+The values used here can later be referenced using the [`layer`](../layer) property.
+The layers defined first in the list are drawn under the layers that are defined later in the list.
+
+More information on layers can be found in the [guide](../guide/layout.md#layers).
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/name.md"
 
 ## Example
 
@@ -31,7 +39,7 @@ However, since `#box1` is on the higher layer, it is drawn on top of `#box2`.
 
 === "layers.css"
 
-    ```sass hl_lines="3 15 19"
+    ```sass hl_lines="3 14 19"
     --8<-- "docs/examples/guide/layout/layers.css"
     ```
 
@@ -46,5 +54,5 @@ layers: below above;
 
 ```python
 # Bottom layer is called 'below', layer above it is called 'above'
-widget.layers = ("below", "above")
+widget.style.layers = ("below", "above")
 ```
diff --git a/docs/styles/layout.md b/docs/styles/layout.md
index a3021f753c..13544bd7e4 100644
--- a/docs/styles/layout.md
+++ b/docs/styles/layout.md
@@ -2,13 +2,13 @@
 
 The `layout` property defines how a widget arranges its children.
 
-See [layout](../guide/layout.md) guide for more information.
-
 ## Syntax
 
-```
-layout: [grid|horizontal|vertical];
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+layout: grid | horizontal | vertical;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The `layout` style takes an option that defines how child widgets will be arranged, as per the table shown below.
 
 ### Values
 
@@ -18,9 +18,12 @@ layout: [grid|horizontal|vertical];
 | `horizontal`         | Child widgets will be arranged along the horizontal axis, from left to right. |
 | `vertical` (default) | Child widgets will be arranged along the vertical axis, from top to bottom.   |
 
+See the [layout](../guide/layout.md) guide for more information.
+
 ## Example
 
 Note how the `layout` property affects the arrangement of widgets in the example below.
+To learn more about the grid layout, you can see the [layout guide](../guide/layout.md) or the [grid reference](../grid).
 
 === "layout.py"
 
@@ -48,5 +51,5 @@ layout: horizontal;
 ## Python
 
 ```python
-widget.layout = "horizontal"
+widget.styles.layout = "horizontal"
 ```
diff --git a/docs/styles/links.md b/docs/styles/links.md
deleted file mode 100644
index 225126aad6..0000000000
--- a/docs/styles/links.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Links
-
-Textual supports the concept of inline "links" embedded in text which trigger an action when pressed.
-
-There are a number of styles which influence the appearance of these links within a widget.
-
-| Property                | Description                                                 |
-|-------------------------|-------------------------------------------------------------|
-| `link-color`            | The color of link text.                                     |
-| `link-background`       | The background color of link text.                          |
-| `link-style`            | The style of link text (e.g. underline).                    |
-| `link-hover-color`      | The color of link text with the cursor above it.            |
-| `link-hover-background` | The background color of link text with the cursor above it. |
-| `link-hover-style`      | The style of link text with the cursor above it.            |
-
-## Syntax
-
-```scss
-link-color: <COLOR>;
-link-background: <COLOR>;
-link-style: <TEXT STYLE> ...;
-link-hover-color: <COLOR>;
-link-hover-background: <COLOR>;
-link-hover-style: <TEXT STYLE> ...;
-```
-
-## Example
-
-In the example below, the first `Static` illustrates default link styling.
-The second `Static` uses CSS to customize the link color, background, and style.
-
-=== "Output"
-
-    ```{.textual path="docs/examples/styles/links.py"}
-    ```
-
-=== "links.py"
-
-    ```python
-    --8<-- "docs/examples/styles/links.py"
-    ```
-
-=== "links.css"
-
-    ```sass
-    --8<-- "docs/examples/styles/links.css"
-    ```
-
-## Additional Notes
-
-* Inline links are not widgets, and thus cannot be focused.
-
-## See Also
-
-* An [introduction to links](../guide/actions.md#links) in the Actions guide.
-
-[//]: # (TODO: Links are documented twice in the guide, and one will likely be removed. Check the link above still works after that.)
diff --git a/docs/styles/links/demos/link_hover_background_demo.gif b/docs/styles/links/demos/link_hover_background_demo.gif
new file mode 100644
index 0000000000..5052b7889d
Binary files /dev/null and b/docs/styles/links/demos/link_hover_background_demo.gif differ
diff --git a/docs/styles/links/demos/link_hover_color_demo.gif b/docs/styles/links/demos/link_hover_color_demo.gif
new file mode 100644
index 0000000000..a2dd07e62e
Binary files /dev/null and b/docs/styles/links/demos/link_hover_color_demo.gif differ
diff --git a/docs/styles/links/demos/link_hover_style_demo.gif b/docs/styles/links/demos/link_hover_style_demo.gif
new file mode 100644
index 0000000000..cc0a699c13
Binary files /dev/null and b/docs/styles/links/demos/link_hover_style_demo.gif differ
diff --git a/docs/styles/links/index.md b/docs/styles/links/index.md
new file mode 100644
index 0000000000..edbc86bb58
--- /dev/null
+++ b/docs/styles/links/index.md
@@ -0,0 +1,81 @@
+# Links
+
+Textual supports the concept of inline "links" embedded in text which trigger an action when pressed.
+There are a number of styles which influence the appearance of these links within a widget.
+
+!!! note
+
+    These CSS rules only target Textual action links. Internet hyperlinks are not affected by these CSS rules.
+
+| Property                                              | Description                                                       |
+|-------------------------------------------------------|-------------------------------------------------------------------|
+| [`link-background`](./link_background.md)             | The background color of the link text.                            |
+| [`link-color`](./link_color.md)                       | The color of the link text.                                       |
+| [`link-hover-background`](./link_hover_background.md) | The background color of the link text when the cursor is over it. |
+| [`link-hover-color`](./link_hover_color.md)           | The color of the link text when the cursor is over it.            |
+| [`link-hover-style`](./link_hover_style.md)           | The style of the link text when the cursor is over it.            |
+| [`link-style`](./link_style.md)                       | The style of the link text (e.g. underline).                      |
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./link_background">link-background</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./link_color">link-color</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./link_style">link-style</a>: <a href="../../css_types/text_style">&lt;text-style&gt;</a>;
+
+<a href="./link_hover_background">link-hover-background</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./link_hover_color">link-hover-color</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./link_hover_style">link-hover-style</a>: <a href="../../css_types/text_style">&lt;text-style&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+Visit each style's reference page to learn more about how the values are used.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+#### &lt;text-style&gt;
+
+--8<-- "docs/snippets/type_syntax/text_style.md"
+
+## Example
+
+In the example below, the first label illustrates default link styling.
+The second label uses CSS to customize the link color, background, and style.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/links.py"}
+    ```
+
+=== "links.py"
+
+    ```python
+    --8<-- "docs/examples/styles/links.py"
+    ```
+
+=== "links.css"
+
+    ```sass
+    --8<-- "docs/examples/styles/links.css"
+    ```
+
+## Additional Notes
+
+* Inline links are not widgets, and thus cannot be focused.
+
+## See Also
+
+* An [introduction to links](../../guide/actions.md#links) in the Actions guide.
+
+[//]: # (TODO: Links are documented twice in the guide, and one will likely be removed. Check the link above still works after that.)
diff --git a/docs/styles/links/link_background.md b/docs/styles/links/link_background.md
new file mode 100644
index 0000000000..92e1e61913
--- /dev/null
+++ b/docs/styles/links/link_background.md
@@ -0,0 +1,71 @@
+# Link-background
+
+The `link-background` sets the background color of the link.
+
+!!! note
+
+    `link-background` only applies to Textual action links as described in the [actions guide](../../guide/actions.md#links) and not to regular hyperlinks.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+link-background: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`link-background` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the background color of text enclosed in Textual action links.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+The example below shows some links with their background color changed.
+It also shows that `link-background` does not affect hyperlinks.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/link_background.py" lines=6}
+    ```
+
+=== "link_background.py"
+
+    ```py hl_lines="8-9 12-13 16-17 20-21"
+    --8<-- "docs/examples/styles/link_background.py"
+    ```
+
+    1. This label has an hyperlink so it won't be affected by the `link-background` rule.
+    2. This label has an "action link" that can be styled with `link-background`.
+    3. This label has an "action link" that can be styled with `link-background`.
+    4. This label has an "action link" that can be styled with `link-background`.
+
+=== "link_background.css"
+
+    ```css hl_lines="2 6 10"
+    --8<-- "docs/examples/styles/link_background.css"
+    ```
+
+    1. This will only affect one of the labels because action links are the only links that this rule affects.
+
+## CSS
+
+```css
+link-background: red 70%;
+link-background: $accent;
+```
+
+## Python
+
+```py
+widget.styles.link_background = "red 70%"
+widget.styles.link_background = "$accent"
+
+# You can also use a `Color` object directly:
+widget.styles.link_background = Color(100, 30, 173)
+```
diff --git a/docs/styles/links/link_color.md b/docs/styles/links/link_color.md
new file mode 100644
index 0000000000..e9ce8c2108
--- /dev/null
+++ b/docs/styles/links/link_color.md
@@ -0,0 +1,71 @@
+# Link-color
+
+The `link-color` sets the color of the link text.
+
+!!! note
+
+    `link-color` only applies to Textual action links as described in the [actions guide](../../guide/actions.md#links) and not to regular hyperlinks.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+link-color: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`link-color` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the color of text enclosed in Textual action links.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+The example below shows some links with their color changed.
+It also shows that `link-color` does not affect hyperlinks.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/link_color.py" lines=6}
+    ```
+
+=== "link_color.py"
+
+    ```py hl_lines="8-9 12-13 16-17 20-21"
+    --8<-- "docs/examples/styles/link_color.py"
+    ```
+
+    1. This label has an hyperlink so it won't be affected by the `link-color` rule.
+    2. This label has an "action link" that can be styled with `link-color`.
+    3. This label has an "action link" that can be styled with `link-color`.
+    4. This label has an "action link" that can be styled with `link-color`.
+
+=== "link_color.css"
+
+    ```css hl_lines="2 6 10"
+    --8<-- "docs/examples/styles/link_color.css"
+    ```
+
+    1. This will only affect one of the labels because action links are the only links that this rule affects.
+
+## CSS
+
+```css
+link-color: red 70%;
+link-color: $accent;
+```
+
+## Python
+
+```py
+widget.styles.link_color = "red 70%"
+widget.styles.link_color = "$accent"
+
+# You can also use a `Color` object directly:
+widget.styles.link_color = Color(100, 30, 173)
+```
diff --git a/docs/styles/links/link_hover_background.md b/docs/styles/links/link_hover_background.md
new file mode 100644
index 0000000000..9da9e27c69
--- /dev/null
+++ b/docs/styles/links/link_hover_background.md
@@ -0,0 +1,81 @@
+# Link-hover-background
+
+The `link-hover-background` sets the background color of the link when the mouse cursor is over the link.
+
+!!! note
+
+    `link-hover-background` only applies to Textual action links as described in the [actions guide](../../guide/actions.md#links) and not to regular hyperlinks.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+link-hover-background: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`link-hover-background` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the background color of text enclosed in Textual action links when the mouse pointer is over it.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+### Defaults
+
+If not provided, a Textual action link will have `link-hover-background` set to `$accent`.
+
+## Example
+
+The example below shows some links that have their background colour changed when the mouse moves over it and it shows that there is a default color for `link-hover-background`.
+
+It also shows that `link-hover-background` does not affect hyperlinks.
+
+=== "Output"
+
+    ![](./demos/link_hover_background_demo.gif)
+
+    !!! note
+
+        The GIF has reduced quality to make it easier to load in the documentation.
+        Try running the example yourself with `textual run docs/examples/styles/link_hover_background.py`.
+
+=== "link_hover_background.py"
+
+    ```py hl_lines="8-9 12-13 16-17 20-21"
+    --8<-- "docs/examples/styles/link_hover_background.py"
+    ```
+
+    1. This label has an hyperlink so it won't be affected by the `link-hover-background` rule.
+    2. This label has an "action link" that can be styled with `link-hover-background`.
+    3. This label has an "action link" that can be styled with `link-hover-background`.
+    4. This label has an "action link" that can be styled with `link-hover-background`.
+
+=== "link_hover_background.css"
+
+    ```css hl_lines="2 6 10"
+    --8<-- "docs/examples/styles/link_hover_background.css"
+    ```
+
+    1. This will only affect one of the labels because action links are the only links that this rule affects.
+    2. The default behavior for links on hover is to change to a different background color, so we don't need to change anything if all we want is to add emphasis to the link under the mouse.
+
+## CSS
+
+```css
+link-hover-background: red 70%;
+link-hover-background: $accent;
+```
+
+## Python
+
+```py
+widget.styles.link_hover_background = "red 70%"
+widget.styles.link_hover_background = "$accent"
+
+# You can also use a `Color` object directly:
+widget.styles.link_hover_background = Color(100, 30, 173)
+```
diff --git a/docs/styles/links/link_hover_color.md b/docs/styles/links/link_hover_color.md
new file mode 100644
index 0000000000..a1f53c4f93
--- /dev/null
+++ b/docs/styles/links/link_hover_color.md
@@ -0,0 +1,84 @@
+# Link-hover-color
+
+The `link-hover-color` sets the color of the link text when the mouse cursor is over the link.
+
+!!! note
+
+    `link-hover-color` only applies to Textual action links as described in the [actions guide](../../guide/actions.md#links) and not to regular hyperlinks.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+link-hover-color: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`link-hover-color` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the color of text enclosed in Textual action links when the mouse pointer is over it.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+### Defaults
+
+If not provided, a Textual action link will have `link-hover-color` set to `white`.
+
+## Example
+
+The example below shows some links that have their colour changed when the mouse moves over it.
+It also shows that `link-hover-color` does not affect hyperlinks.
+
+=== "Output"
+
+    ![](./demos/link_hover_color_demo.gif)
+
+    !!! note
+
+        The background color also changes when the mouse moves over the links because that is the default behavior.
+        That can be customised by setting [`link-hover-background`](./link_hover_background.md) but we haven't done so in this example.
+
+    !!! note
+
+        The GIF has reduced quality to make it easier to load in the documentation.
+        Try running the example yourself with `textual run docs/examples/styles/link_hover_color.py`.
+
+=== "link_hover_color.py"
+
+    ```py hl_lines="8-9 12-13 16-17 20-21"
+    --8<-- "docs/examples/styles/link_hover_color.py"
+    ```
+
+    1. This label has an hyperlink so it won't be affected by the `link-hover-color` rule.
+    2. This label has an "action link" that can be styled with `link-hover-color`.
+    3. This label has an "action link" that can be styled with `link-hover-color`.
+    4. This label has an "action link" that can be styled with `link-hover-color`.
+
+=== "link_hover_color.css"
+
+    ```css hl_lines="2 6 10"
+    --8<-- "docs/examples/styles/link_hover_color.css"
+    ```
+
+    1. This will only affect one of the labels because action links are the only links that this rule affects.
+
+## CSS
+
+```css
+link-hover-color: red 70%;
+link-hover-color: black;
+```
+
+## Python
+
+```py
+widget.styles.link_hover_color = "red 70%"
+widget.styles.link_hover_color = "black"
+
+# You can also use a `Color` object directly:
+widget.styles.link_hover_color = Color(100, 30, 173)
+```
diff --git a/docs/styles/links/link_hover_style.md b/docs/styles/links/link_hover_style.md
new file mode 100644
index 0000000000..3a9d429db3
--- /dev/null
+++ b/docs/styles/links/link_hover_style.md
@@ -0,0 +1,76 @@
+# Link-hover-style
+
+The `link-hover-style` sets the text style for the link text when the mouse cursor is over the link.
+
+!!! note
+
+    `link-hover-style` only applies to Textual action links as described in the [actions guide](../../guide/actions.md#links) and not to regular hyperlinks.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+link-hover-style: <a href="../../css_types/text_style">&lt;text-style&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`link-hover-style` applies its [`<text-style>`](../../../css_types/text_style) to the text of Textual action links when the mouse pointer is over them.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/text_style.md"
+
+### Defaults
+
+If not provided, a Textual action link will have `link-hover-style` set to `bold`.
+
+## Example
+
+The example below shows some links that have their colour changed when the mouse moves over it.
+It also shows that `link-hover-style` does not affect hyperlinks.
+
+=== "Output"
+
+    ![](./demos/link_hover_style_demo.gif)
+
+    !!! note
+
+        The background color also changes when the mouse moves over the links because that is the default behavior.
+        That can be customised by setting [`link-hover-background`](./link_hover_background.md) but we haven't done so in this example.
+
+    !!! note
+
+        The GIF has reduced quality to make it easier to load in the documentation.
+        Try running the example yourself with `textual run docs/examples/styles/link_hover_style.py`.
+
+=== "link_hover_style.py"
+
+    ```py hl_lines="8-9 12-13 16-17 20-21"
+    --8<-- "docs/examples/styles/link_hover_style.py"
+    ```
+
+    1. This label has an hyperlink so it won't be affected by the `link-hover-style` rule.
+    2. This label has an "action link" that can be styled with `link-hover-style`.
+    3. This label has an "action link" that can be styled with `link-hover-style`.
+    4. This label has an "action link" that can be styled with `link-hover-style`.
+
+=== "link_hover_style.css"
+
+    ```css hl_lines="2 6 10"
+    --8<-- "docs/examples/styles/link_hover_style.css"
+    ```
+
+    1. This will only affect one of the labels because action links are the only links that this rule affects.
+    2. The default behavior for links on hover is to change to a different text style, so we don't need to change anything if all we want is to add emphasis to the link under the mouse.
+
+## CSS
+
+```css
+link-hover-style: bold;
+link-hover-style: bold italic reverse;
+```
+
+## Python
+
+```py
+widget.styles.link_hover_style = "bold"
+widget.styles.link_hover_style = "bold italic reverse"
+```
diff --git a/docs/styles/links/link_style.md b/docs/styles/links/link_style.md
new file mode 100644
index 0000000000..336e5a437c
--- /dev/null
+++ b/docs/styles/links/link_style.md
@@ -0,0 +1,66 @@
+# Link-style
+
+The `link-style` sets the text style for the link text.
+
+!!! note
+
+    `link-style` only applies to Textual action links as described in the [actions guide](../../guide/actions.md#links) and not to regular hyperlinks.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+link-style: <a href="../../css_types/text_style">&lt;text-style&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`link-style` will take all the values specified and will apply that styling to text that is enclosed by a Textual action link.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/text_style.md"
+
+### Defaults
+
+If not provided, a Textual action link will have `link-style` set to `underline`.
+
+## Example
+
+The example below shows some links with different styles applied to their text.
+It also shows that `link-style` does not affect hyperlinks.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/link_style.py" lines=6}
+    ```
+
+=== "link_style.py"
+
+    ```py hl_lines="8-9 12-13 16-17 20-21"
+    --8<-- "docs/examples/styles/link_style.py"
+    ```
+
+    1. This label has an hyperlink so it won't be affected by the `link-style` rule.
+    2. This label has an "action link" that can be styled with `link-style`.
+    3. This label has an "action link" that can be styled with `link-style`.
+    4. This label has an "action link" that can be styled with `link-style`.
+
+=== "link_style.css"
+
+    ```css hl_lines="2 6 10"
+    --8<-- "docs/examples/styles/link_style.css"
+    ```
+
+    1. This will only affect one of the labels because action links are the only links that this rule affects.
+
+## CSS
+
+```css
+link-style: bold;
+link-style: bold italic reverse;
+```
+
+## Python
+
+```py
+widget.styles.link_style = "bold"
+widget.styles.link_style = "bold italic reverse"
+```
diff --git a/docs/styles/margin.md b/docs/styles/margin.md
index 21cab8c619..de97a31f7a 100644
--- a/docs/styles/margin.md
+++ b/docs/styles/margin.md
@@ -1,26 +1,49 @@
 # Margin
 
-The `margin` rule adds space around the entire widget. Margin may be specified with 1, 2 or 4 values.
+The `margin` rule specifies spacing around a widget.
 
-| Example            | Description                                                         |
-|--------------------|---------------------------------------------------------------------|
-| `margin: 1;`       | A single value sets a margin of 1 around all 4 edges                |
-| `margin: 1 2;`     | Two values sets the margin for the top/bottom and left/right edges  |
-| `margin: 1 2 3 4;` | Four values sets top, right, bottom, and left margins independently |
+## Syntax
 
-Margin may also be set individually by setting `margin-top`, `margin-right`, `margin-bottom`, or `margin-left` to a single value.
+--8<-- "docs/snippets/syntax_block_start.md"
+margin: <a href="../../css_types/integer">&lt;integer&gt;</a>
+      # one value for all edges
+      | <a href="../../css_types/integer">&lt;integer&gt;</a> <a href="../../css_types/integer">&lt;integer&gt;</a>
+      # top/bot   left/right
+      | <a href="../../css_types/integer">&lt;integer&gt;</a> <a href="../../css_types/integer">&lt;integer&gt;</a> <a href="../../css_types/integer">&lt;integer&gt;</a> <a href="../../css_types/integer">&lt;integer&gt;</a>;
+      # top       right     bot       left
 
-## Syntax
+margin-top: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+margin-right: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+margin-bottom: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+margin-left: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
 
-```
-margin: <INTEGER>;
-margin: <INTEGER> <INTEGER>;
-margin: <INTEGER> <INTEGER> <INTEGER> <INTEGER>;
-```
+The `margin` specifies spacing around the four edges of the widget equal to the [`<integer>`](../../css_types/integer) specified.
+The number of values given defines what edges get what margin:
+
+ - 1 [`<integer>`](../../css_types/integer) sets the same margin for the four edges of the widget;
+ - 2 [`<integer>`](../../css_types/integer) set margin for top/bottom and left/right edges, respectively.
+ - 4 [`<integer>`](../../css_types/integer) set margin for the top, right, bottom, and left edges, respectively.
+
+!!! tip
+
+    To remember the order of the edges affected by the rule `margin` when it has 4 values, think of a clock.
+    Its hand starts at the top and the goes clockwise: top, right, bottom, left.
 
-## Example
+Alternatively, margin can be set for each edge individually through the rules `margin-top`, `margin-right`, `margin-bottom`, and `margin-left`, respectively.
 
-In this example we add a large margin to some static text.
+### Values
+
+--8<-- "docs/snippets/type_syntax/integer.md"
+
+## Examples
+
+In the example below we add a large margin to a label, which makes it move away from the top-left corner of the screen.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/margin.py"}
+    ```
 
 === "margin.py"
 
@@ -34,21 +57,54 @@ In this example we add a large margin to some static text.
     --8<-- "docs/examples/styles/margin.css"
     ```
 
+The next example shows a grid.
+In each cell, we have a placeholder that has its margins set in different ways.
+
 === "Output"
 
-    ```{.textual path="docs/examples/styles/margin.py"}
+    ```{.textual path="docs/examples/styles/margin_all.py"}
+    ```
+
+=== "margin_all.py"
+
+    ```py
+    --8<-- "docs/examples/styles/margin_all.py"
+    ```
+
+=== "margin_all.css"
+
+    ```py
+    --8<-- "docs/examples/styles/margin_all.css"
     ```
 
 ## CSS
 
 ```sass
+/* Set margin of 1 around all edges */
+margin: 1
 /* Set margin of 2 on the top and bottom edges, and 4 on the left and right */
 margin: 2 4;
+/* Set margin of 1 on the top, 2 on the right,
+                 3 on the bottom, and 4 on the left */
+margin: 1 2 3 4;
+
+margin-top: 1;
+margin-right: 2;
+margin-bottom: 3;
+margin-left: 4;
 ```
 
 ## Python
 
+In Python, you cannot set any of the individual `margin` rules `margin-top`, `margin-right`, `margin-bottom`, and `margin-left`.
+
+However, you _can_ set margin to a single integer, a tuple of 2 integers, or a tuple of 4 integers:
+
 ```python
-# In Python you can set the margin as a tuple of integers
-widget.styles.margin = (2, 3)
+# Set margin of 1 around all edges
+widget.styles.margin = 1
+# Set margin of 2 on the top and bottom edges, and 4 on the left and right
+widget.styles.margin = (2, 4)
+# Set margin of 1 on top, 2 on the right, 3 on the bottom, and 4 on the left
+widget.styles.margin = (1, 2, 3, 4)
 ```
diff --git a/docs/styles/max_height.md b/docs/styles/max_height.md
index e80d996fec..c14162517b 100644
--- a/docs/styles/max_height.md
+++ b/docs/styles/max_height.md
@@ -4,18 +4,48 @@ The `max-height` rule sets a maximum height for a widget.
 
 ## Syntax
 
-```
-max-height: <SCALAR>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+max-height: <a href="../../css_types/scalar">&lt;scalar&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The `max-height` rule accepts a [`<scalar>`](../../css_types/scalar) that defines an upper bound for the [`height`](./height) of a widget.
+That is, the height of a widget is never allowed to exceed `max-height`.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
+
+## Example
+
+The example below shows some placeholders that were defined to span vertically from the top edge of the terminal to the bottom edge.
+Then, we set `max-height` individually on each placeholder.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/max_height.py"}
+    ```
+
+=== "max_height.py"
+
+    ```py
+    --8<-- "docs/examples/styles/max_height.py"
+    ```
+
+=== "max_height.css"
+
+    ```css
+    --8<-- "docs/examples/styles/max_height.css"
+    ```
+
+    1. This won't affect the placeholder because its height is less than the maximum height.
 
 ## CSS
 
 ```sass
-
-/* Set a maximum height of 10 rows */
+/* Set the maximum height to 10 rows */
 max-height: 10;
 
-/* Set a maximum height of 25% of the screen height */
+/* Set the maximum height to 25% of the viewport height */
 max-height: 25vh;
 ```
 
@@ -25,7 +55,6 @@ max-height: 25vh;
 # Set the maximum height to 10 rows
 widget.styles.max_height = 10
 
-# Set the maximum height to 25% of the screen height
+# Set the maximum height to 25% of the viewport height
 widget.styles.max_height = "25vh"
-
 ```
diff --git a/docs/styles/max_width.md b/docs/styles/max_width.md
index c6ce4ef679..41d07b3152 100644
--- a/docs/styles/max_width.md
+++ b/docs/styles/max_width.md
@@ -4,27 +4,57 @@ The `max-width` rule sets a maximum width for a widget.
 
 ## Syntax
 
-```
-max-width: <SCALAR>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+max-width: <a href="../../css_types/scalar">&lt;scalar&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The `max-width` rule accepts a [`<scalar>`](../../css_types/scalar) that defines an upper bound for the [`width`](./width) of a widget.
+That is, the width of a widget is never allowed to exceed `max-width`.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
+
+## Example
+
+The example below shows some placeholders that were defined to span horizontally from the top edge of the terminal to the bottom edge.
+Then, we set `max-width` individually on each placeholder.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/max_width.py"}
+    ```
+
+=== "max_width.py"
+
+    ```py
+    --8<-- "docs/examples/styles/max_width.py"
+    ```
+
+=== "max_width.css"
+
+    ```scss
+    --8<-- "docs/examples/styles/max_width.css"
+    ```
+
+    1. This won't affect the placeholder because its width is less than the maximum width.
 
 ## CSS
 
 ```sass
-
-/* Set a maximum width of 10 cells */
+/* Set the maximum width to 10 rows */
 max-width: 10;
 
-/* Set a maximum width of 25% of the screen width */
-max-width: 25vw;
+/* Set the maximum width to 25% of the viewport width */
+max-width: 25vh;
 ```
 
 ## Python
 
 ```python
-# Set the maximum width to 10 cells
+# Set the maximum width to 10 rows
 widget.styles.max_width = 10
 
-# Set the maximum width to 25% of the screen width
-widget.styles.max_width = "25vw"
+# Set the maximum width to 25% of the viewport width
+widget.styles.max_width = "25vh"
 ```
diff --git a/docs/styles/min_height.md b/docs/styles/min_height.md
index b110e190eb..79adb93bbd 100644
--- a/docs/styles/min_height.md
+++ b/docs/styles/min_height.md
@@ -4,18 +4,48 @@ The `min-height` rule sets a minimum height for a widget.
 
 ## Syntax
 
-```
-min-height: <SCALAR>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+min-height: <a href="../../css_types/scalar">&lt;scalar&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The `min-height` rule accepts a [`<scalar>`](../../css_types/scalar) that defines a lower bound for the [`height`](./height) of a widget.
+That is, the height of a widget is never allowed to be under `min-height`.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
+
+## Example
+
+The example below shows some placeholders with their height set to `50%`.
+Then, we set `min-height` individually on each placeholder.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/min_height.py"}
+    ```
+
+=== "min_height.py"
+
+    ```py
+    --8<-- "docs/examples/styles/min_height.py"
+    ```
+
+=== "min_height.css"
+
+    ```css hl_lines="13"
+    --8<-- "docs/examples/styles/min_height.css"
+    ```
+
+    1. This won't affect the placeholder because its height is larger than the minimum height.
 
 ## CSS
 
 ```sass
-
-/* Set a minimum height of 10 rows */
+/* Set the minimum height to 10 rows */
 min-height: 10;
 
-/* Set a minimum height of 25% of the screen height */
+/* Set the minimum height to 25% of the viewport height */
 min-height: 25vh;
 ```
 
@@ -23,9 +53,8 @@ min-height: 25vh;
 
 ```python
 # Set the minimum height to 10 rows
-self.styles.min_height = 10
-
-# Set the minimum height to 25% of the screen height
-self.styles.min_height = "25vh"
+widget.styles.min_height = 10
 
+# Set the minimum height to 25% of the viewport height
+widget.styles.min_height = "25vh"
 ```
diff --git a/docs/styles/min_width.md b/docs/styles/min_width.md
index 81331469ac..4db00c5e4b 100644
--- a/docs/styles/min_width.md
+++ b/docs/styles/min_width.md
@@ -1,30 +1,60 @@
 # Min-width
 
-The `min-width` rules sets a minimum width for a widget.
+The `min-width` rule sets a minimum width for a widget.
 
 ## Syntax
 
-```
-min-width: <SCALAR>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+min-width: <a href="../../css_types/scalar">&lt;scalar&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The `min-width` rule accepts a [`<scalar>`](../../css_types/scalar) that defines a lower bound for the [`width`](./width) of a widget.
+That is, the width of a widget is never allowed to be under `min-width`.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
+
+## Example
+
+The example below shows some placeholders with their width set to `50%`.
+Then, we set `min-width` individually on each placeholder.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/min_width.py"}
+    ```
+
+=== "min_width.py"
+
+    ```py
+    --8<-- "docs/examples/styles/min_width.py"
+    ```
+
+=== "min_width.css"
+
+    ```css hl_lines="13"
+    --8<-- "docs/examples/styles/min_width.css"
+    ```
+
+    1. This won't affect the placeholder because its width is larger than the minimum width.
 
 ## CSS
 
 ```sass
-
-/* Set a minimum width of 10 cells */
+/* Set the minimum width to 10 rows */
 min-width: 10;
 
-/* Set a minimum width of 25% of the screen width */
-min-width: 25vw;
+/* Set the minimum width to 25% of the viewport width */
+min-width: 25vh;
 ```
 
 ## Python
 
 ```python
-# Set the minimum width to 10 cells
+# Set the minimum width to 10 rows
 widget.styles.min_width = 10
 
-# Set the minimum width to 25% of the screen width
-widget.styles.min_width = "25vw"
+# Set the minimum width to 25% of the viewport width
+widget.styles.min_width = "25vh"
 ```
diff --git a/docs/styles/offset.md b/docs/styles/offset.md
index 059a1edbe7..10ca2dd4db 100644
--- a/docs/styles/offset.md
+++ b/docs/styles/offset.md
@@ -1,19 +1,33 @@
 # Offset
 
-The `offset` rule adds an offset to the widget's position. The offset is given as two values.
-
-Coordinates may be specified individually with `offset-x` and `offset-y`.
+The `offset` rule defines an offset for the position of the widget.
 
 ## Syntax
 
-```
-offset: <SCALAR> <SCALAR>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+offset: <a href="../../css_types/scalar">&lt;scalar&gt;</a> <a href="../../css_types/scalar">&lt;scalar&gt;</a>;
+
+offset-x: <a href="../../css_types/scalar">&lt;scalar&gt;</a>;
+offset-y: <a href="../../css_types/scalar">&lt;scalar&gt;</a> 
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The two [`<scalar>`](../../css_types/scalar) in the `offset` define, respectively, the offsets in the horizontal and vertical axes for the widget.
+
+To specify an offset along a single axis, you can use `offset-x` and `offset-y`.
+
+### Values
+
+--8<-- "docs/snippets/type_syntax/scalar.md"
 
 ## Example
 
 In this example, we have 3 widgets with differing offsets.
 
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/offset.py"}
+    ```
+
 === "offset.py"
 
     ```python
@@ -26,20 +40,23 @@ In this example, we have 3 widgets with differing offsets.
     --8<-- "docs/examples/styles/offset.css"
     ```
 
-=== "Output"
-
-    ```{.textual path="docs/examples/styles/offset.py"}
-    ```
-
 ## CSS
 
 ```sass
-/* Move the widget 2 cells in the x direction, and 4 in the y direction. */
-offset: 2 4;
+/* Move the widget 8 cells in the x direction and 2 in tye y direction */
+offset: 8 2;
+
+/* Move the widget 4 cells in the x direction
+offset-x: 4;
+/* Move the widget -2 cells in the y direction
+offset-y: -2;
 ```
 
 ## Python
 
+You cannot change programmatically the offset for a single axis.
+You have to set the two axes at the same time.
+
 ```python
 # Move the widget 2 cells in the x direction, and 4 in the y direction.
 widget.styles.offset = (2, 4)
diff --git a/docs/styles/opacity.md b/docs/styles/opacity.md
index 1ccff5458d..4844f9342f 100644
--- a/docs/styles/opacity.md
+++ b/docs/styles/opacity.md
@@ -1,24 +1,34 @@
 # Opacity
 
-The `opacity` property can be used to make a widget partially or fully transparent.
-
+The `opacity` property sets the opacity/transparency of a widget.
 
 ## Syntax
 
-```
-opacity: <FRACTIONAL>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+opacity: <a href="../../css_types/number">&lt;number&gt;</a> | <a href="../../css_types/percentage">&lt;percentage&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The opacity of a widget can be set as a [`<number>`](../css_types/number.md)  or a [`<percentage>`](../css_types/percentage.md).
+`0`/`0%` means no opacity, which is equivalent to full transparency.
+Conversely, `1`/`100%` means full opacity, which is equivalent to no transparency.
+Values outside of these ranges will be clamped.
 
 ### Values
 
-As a fractional property, `opacity` can be set to either a float (between 0 and 1),
-or a percentage, e.g. `45%`.
-Float values will be clamped between 0 and 1.
-Percentage values will be clamped between 0% and 100%.
+### &lt;number&gt;
+
+--8<-- "docs/snippets/type_syntax/number.md"
+The value of [`<number>`](../../css_types/number) is clamped between `0` and `1`.
+
+### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+The value of [`<percentage>`](../../css_types/percentage) is clamped between `0%` and `100%`.
 
 ## Example
 
-This example shows, from top to bottom, increasing opacity values.
+This example shows, from top to bottom, increasing opacity values for a label with a border and some text.
+When the opacity is zero, all we see is the (black) background.
 
 === "opacity.py"
 
diff --git a/docs/styles/outline.md b/docs/styles/outline.md
index 284c669a8d..3d19160901 100644
--- a/docs/styles/outline.md
+++ b/docs/styles/outline.md
@@ -1,50 +1,46 @@
 # Outline
 
-The `outline` rule enables the drawing of a box around a widget. Similar to `border`, but unlike border, outline will
-draw _over_ the content area. This rule can be useful for emphasis if you want to display an outline for a brief time to
-draw the user's attention to it.
+The `outline` rule enables the drawing of a box around the content of a widget, which means the outline is drawn _over_ the content area.
 
-An outline is set with a border value (see table below) followed by a color.
+!!! warning
 
-Outlines may also be set individually with the `outline-top`, `outline-right`, `outline-bottom` and `outline-left`
-rules.
+    Not to be confused with [`border`](./border.md).
 
 ## Syntax
 
-```
-outline: [<COLOR>] [<BORDER VALUE>];
-outline-top: [<COLOR>] [<BORDER VALUE>];
-outline-right: [<COLOR>] [<BORDER VALUE>];
-outline-bottom: [<COLOR>] [<BORDER VALUE>];
-outline-left: [<COLOR>] [<BORDER VALUE>];
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+outline: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+
+outline-top: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+outline-right: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+outline-bottom: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+outline-left: [<a href="../../css_types/border">&lt;border&gt;</a>] [<a href="../../css_types/color">&lt;color&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The style `outline` accepts an optional [`<border>`](../../css_types/border) that sets the visual style of the widget outline and an optional [`<color>`](../../css_types/color) to set the color of the outline.
+
+Unlike the style [`border`](./border.md), the frame of the outline is drawn over the content area of the widget.
+This rule can be useful for temporary emphasis of the content of a widget, if you want to draw the user's attention to it.
 
 ### Values
 
-| Border value | Description                                             |
-|--------------|---------------------------------------------------------|
-| `"ascii"`    | A border with plus, hyphen, and vertical bar            |
-| `"blank"`    | A blank border (reserves space for a border)            |
-| `"dashed"`   | Dashed line border                                      |
-| `"double"`   | Double lined border                                     |
-| `"heavy"`    | Heavy border                                            |
-| `"hidden"`   | Alias for "none"                                        |
-| `"hkey"`     | Horizontal key-line border                              |
-| `"inner"`    | Thick solid border                                      |
-| `"none"`     | Disabled border                                         |
-| `"outer"`    | Think solid border with additional space around content |
-| `"round"`    | Rounded corners                                         |
-| `"solid"`    | Solid border                                            |
-| `"tall"`     | Solid border with extras space top and bottom           |
-| `"vkey"`     | Vertical key-line border                                |
-| `"wide"`     | Solid border with additional space left and right       |
-
-For example, `heavy white` would display a heavy white line around a widget.
-
-## Example
+#### &lt;border&gt;
+
+--8<-- "docs/snippets/type_syntax/border.md"
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+## Examples
 
 This example shows a widget with an outline. Note how the outline occludes the text area.
 
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/outline.py"}
+    ```
+
 === "outline.py"
 
     ```python
@@ -57,9 +53,25 @@ This example shows a widget with an outline. Note how the outline occludes the t
     --8<-- "docs/examples/styles/outline.css"
     ```
 
+The next example makes the difference clearer, by having three labels side-by-side.
+They contain the same text, have the same width and height, and are styled exactly the same up to their `outline` and [`border`](./border.md) rules.
+This example also shows that a widget can contain both a `border` and an `outline`:
+
 === "Output"
 
-    ```{.textual path="docs/examples/styles/outline.py"}
+    ```{.textual path="docs/examples/styles/outline_vs_border.py"}
+    ```
+
+=== "outline_vs_border.py"
+
+    ```python
+    --8<-- "docs/examples/styles/outline_vs_border.py"
+    ```
+
+=== "outline_vs_border.css"
+
+    ```css
+    --8<-- "docs/examples/styles/outline_vs_border.css"
     ```
 
 ## CSS
@@ -76,8 +88,8 @@ outline-left:outer red;
 
 ```python
 # Set a heavy white outline
-widget.outline = ("heavy", "white)
+widget.outline = ("heavy", "white")
 
 # Set a red outline on the left
-widget.outline_left = ("outer", "red)
+widget.outline_left = ("outer", "red")
 ```
diff --git a/docs/styles/overflow.md b/docs/styles/overflow.md
index 7b49ec4f14..84a903fd1c 100644
--- a/docs/styles/overflow.md
+++ b/docs/styles/overflow.md
@@ -1,35 +1,48 @@
 # Overflow
 
-The `overflow` rule specifies if and when scrollbars should be displayed on the `x` and `y` axis.
-The rule takes two overflow values; one for the horizontal bar (x-axis), followed by the vertical bar (y-axis).
+The `overflow` rule specifies if and when scrollbars should be displayed.
 
-The default value for overflow is `"auto auto"` which will show scrollbars automatically for both scrollbars if content doesn't fit within container.
+## Syntax
 
-Overflow may also be set independently by setting the `overflow-x` rule for the horizontal bar, and `overflow-y` for the vertical bar.
+--8<-- "docs/snippets/syntax_block_start.md"
+overflow: <a href="../../css_types/overflow">&lt;overflow&gt;</a> <a href="../../css_types/overflow">&lt;overflow&gt;</a>;
 
-## Syntax
+overflow-x: <a href="../../css_types/overflow">&lt;overflow&gt;</a>;
+overflow-y: <a href="../../css_types/overflow">&lt;overflow&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
 
-```
-overflow: [auto|hidden|scroll];
-overflow-x: [auto|hidden|scroll];
-overflow-y: [auto|hidden|scroll];
-```
+The style `overflow` accepts two values that determine when to display scrollbars in a container widget.
+The two values set the overflow for the horizontal and vertical axes, respectively.
+
+Overflow may also be set individually for each axis:
+
+ - `overflow-x` sets the overflow for the horizontal axis; and
+ - `overflow-y` sets the overflow for the vertical axis.
 
 ### Values
 
-| Value            | Description                                             |
-|------------------|---------------------------------------------------------|
-| `auto` (default) | Automatically show the scrollbar if content doesn't fit |
-| `hidden`         | Never show the scrollbar                                |
-| `scroll`         | Always show the scrollbar                               |
+--8<-- "docs/snippets/type_syntax/overflow.md"
+
+### Defaults
+
+The default setting for containers is `overflow: auto auto`.
+
+!!! warning
+
+    Some built-in containers like `Horizontal` and `Vertical` override these defaults.
 
 ## Example
 
-Here we split the screen in to left and right sections, each with three vertically scrolling widgets that do not fit in to the height of the terminal.
+Here we split the screen into left and right sections, each with three vertically scrolling widgets that do not fit into the height of the terminal.
 
 The left side has `overflow-y: auto` (the default) and will automatically show a scrollbar.
 The right side has `overflow-y: hidden` which will prevent a scrollbar from being shown.
 
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/overflow.py"}
+    ```
+
 === "overflow.py"
 
     ```python
@@ -42,11 +55,6 @@ The right side has `overflow-y: hidden` which will prevent a scrollbar from bein
     --8<-- "docs/examples/styles/overflow.css"
     ```
 
-=== "Output"
-
-    ```{.textual path="docs/examples/styles/overflow.py"}
-    ```
-
 ## CSS
 
 ```sass
@@ -62,11 +70,12 @@ overflow-x: scroll;
 
 ## Python
 
+Overflow cannot be programmatically set for both axes at the same time.
+
 ```python
 # Hide the vertical scrollbar
 widget.styles.overflow_y = "hidden"
 
 # Always show the horizontal scrollbar
 widget.styles.overflow_x = "scroll"
-
 ```
diff --git a/docs/styles/padding.md b/docs/styles/padding.md
index 6336a3d5f1..439ed2a9e4 100644
--- a/docs/styles/padding.md
+++ b/docs/styles/padding.md
@@ -1,26 +1,44 @@
 # Padding
 
-The padding rule adds space around the content of a widget. You can specify padding with 1, 2 or 4 numbers.
+The `padding` rule specifies spacing around the content of a widget.
 
-| example             |                                                                     |
-| ------------------- | ------------------------------------------------------------------- |
-| `padding: 1;`       | A single value sets a padding of 1 around all 4 edges               |
-| `padding: 1 2;`     | Two values sets the padding for the top/bottom and left/right edges |
-| `padding: 1 2 3 4;` | Four values sets top, right, bottom, and left padding independently |
+## Syntax
 
-Padding may also be set individually by setting `padding-top`, `padding-right`, `padding-bottom`, or `padding-left` to a single value.
+--8<-- "docs/snippets/syntax_block_start.md"
+padding: <a href="../../css_types/integer">&lt;integer&gt;</a> # one value for all edges
+       | <a href="../../css_types/integer">&lt;integer&gt;</a> <a href="../../css_types/integer">&lt;integer&gt;</a>
+       # top/bot   left/right
+       | <a href="../../css_types/integer">&lt;integer&gt;</a> <a href="../../css_types/integer">&lt;integer&gt;</a> <a href="../../css_types/integer">&lt;integer&gt;</a> <a href="../../css_types/integer">&lt;integer&gt;</a>;
+       # top       right     bot       left
 
-## Syntax
+padding-top: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+padding-right: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+padding-bottom: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+padding-left: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
 
-```
-padding: <INTEGER>;
-padding: <INTEGER> <INTEGER>;
-padding: <INTEGER> <INTEGER> <INTEGER> <INTEGER>;
-```
+The `padding` specifies spacing around the _content_ of a widget, thus this spacing is added _inside_ the widget.
+The values of the [`<integer>`](../../css_types/integer) determine how much spacing is added and the number of values define what edges get what padding:
+
+ - 1 [`<integer>`](../../css_types/integer) sets the same padding for the four edges of the widget;
+ - 2 [`<integer>`](../../css_types/integer) set padding for top/bottom and left/right edges, respectively.
+ - 4 [`<integer>`](../../css_types/integer) set padding for the top, right, bottom, and left edges, respectively.
+
+!!! tip
+
+    To remember the order of the edges affected by the rule `padding` when it has 4 values, think of a clock.
+    Its hand starts at the top and the goes clockwise: top, right, bottom, left.
+
+Alternatively, padding can be set for each edge individually through the rules `padding-top`, `padding-right`, `padding-bottom`, and `padding-left`, respectively.
 
 ## Example
 
-This example adds padding around static text.
+This example adds padding around some text.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/padding.py"}
+    ```
 
 === "padding.py"
 
@@ -34,21 +52,34 @@ This example adds padding around static text.
     --8<-- "docs/examples/styles/padding.css"
     ```
 
-=== "Output"
-
-    ```{.textual path="docs/examples/styles/padding.py"}
-    ```
-
 ## CSS
 
 ```sass
+/* Set padding of 1 around all edges */
+padding: 1
 /* Set padding of 2 on the top and bottom edges, and 4 on the left and right */
 padding: 2 4;
+/* Set padding of 1 on the top, 2 on the right,
+                 3 on the bottom, and 4 on the left */
+padding: 1 2 3 4;
+
+padding-top: 1;
+padding-right: 2;
+padding-bottom: 3;
+padding-left: 4;
 ```
 
 ## Python
 
+In Python, you cannot set any of the individual `padding` rules `padding-top`, `padding-right`, `padding-bottom`, and `padding-left`.
+
+However, you _can_ set padding to a single integer, a tuple of 2 integers, or a tuple of 4 integers:
+
 ```python
-# In Python you can set the padding as a tuple of integers
-widget.styles.padding = (2, 3)
+# Set padding of 1 around all edges
+widget.styles.padding = 1
+# Set padding of 2 on the top and bottom edges, and 4 on the left and right
+widget.styles.padding = (2, 4)
+# Set padding of 1 on top, 2 on the right, 3 on the bottom, and 4 on the left
+widget.styles.padding = (1, 2, 3, 4)
 ```
diff --git a/docs/styles/scrollbar.md b/docs/styles/scrollbar.md
deleted file mode 100644
index 3a4ec1f336..0000000000
--- a/docs/styles/scrollbar.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# Scrollbar colors
-
-There are a number of rules to set the colors used in Textual scrollbars.
-You won't typically need to do this, as the default themes have carefully chosen colors, but you can if you want to.
-
-| Rule                          | Color                                                   |
-|-------------------------------|---------------------------------------------------------|
-| `scrollbar-color`             | Scrollbar "thumb" (movable part)                        |
-| `scrollbar-color-hover`       | Scrollbar thumb when the mouse is hovering over it      |
-| `scrollbar-color-active`      | Scrollbar thumb when it is active (being dragged)       |
-| `scrollbar-background`        | Scrollbar background                                    |
-| `scrollbar-background-hover`  | Scrollbar background when the mouse is hovering over it |
-| `scrollbar-background-active` | Scrollbar background when the thumb is being dragged    |
-| `scrollbar-corner-color`      | The gap between the horizontal and vertical scrollbars  |
-
-## Syntax
-
-```
-scrollbar-color: <COLOR>;
-scrollbar-color-hover: <COLOR>;
-scrollbar-color-active: <COLOR>;
-scrollbar-background: <COLOR>;
-scrollbar-background-hover: <COLOR>;
-scrollbar-background-active: <COLOR>;
-scrollbar-corner-color: <COLOR>;
-```
-
-## Example
-
-In this example we have two panels with different scrollbar colors set for each.
-
-=== "scrollbars.py"
-
-    ```python
-    --8<-- "docs/examples/styles/scrollbars.py"
-    ```
-
-=== "scrollbars.css"
-
-    ```css
-    --8<-- "docs/examples/styles/scrollbars.css"
-    ```
-
-=== "Output"
-
-    ```{.textual path="docs/examples/styles/scrollbars.py"}
-    ```
-
-## CSS
-
-```sass
-/* Set widget scrollbar color to yellow */
-Widget {
-    scrollbar-color: yellow;
-}
-```
-
-## Python
-
-```python
-# Set the scrollbar color to yellow
-widget.styles.scrollbar_color = "yellow"
-```
diff --git a/docs/styles/scrollbar_colors/index.md b/docs/styles/scrollbar_colors/index.md
new file mode 100644
index 0000000000..f3dd5b0931
--- /dev/null
+++ b/docs/styles/scrollbar_colors/index.md
@@ -0,0 +1,66 @@
+# Scrollbar colors
+
+There are a number of rules to set the colors used in Textual scrollbars.
+You won't typically need to do this, as the default themes have carefully chosen colors, but you can if you want to.
+
+| Rule                                                              | Applies to                                               |
+|-------------------------------------------------------------------|----------------------------------------------------------|
+| [`scrollbar-background`](./scrollbar_background.md)               | Scrollbar background.                                    |
+| [`scrollbar-background-active`](./scrollbar_background_active.md) | Scrollbar background when the thumb is being dragged.    |
+| [`scrollbar-background-hover`](./scrollbar_background_hover.md)   | Scrollbar background when the mouse is hovering over it. |
+| [`scrollbar-color`](./scrollbar_color.md)                         | Scrollbar "thumb" (movable part).                        |
+| [`scrollbar-color-active`](./scrollbar_color_active.md)           | Scrollbar thumb when it is active (being dragged).       |
+| [`scrollbar-color-hover`](./scrollbar_color_hover.md)             | Scrollbar thumb when the mouse is hovering over it.      |
+| [`scrollbar-corner-color`](./scrollbar_corner_color.md)           | The gap between the horizontal and vertical scrollbars.  |
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./scrollbar_background">scrollbar-background</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./scrollbar_background_active">scrollbar-background-active</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./scrollbar_background_hover">scrollbar-background-hover</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./scrollbar_color">scrollbar-color</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./scrollbar_color_active">scrollbar-color-active</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./scrollbar_color_hover">scrollbar-color-hover</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+
+<a href="./scrollbar_corner_color">scrollbar-corner-color</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+Visit each style's reference page to learn more about how the values are used.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+This example shows two planels that contain oversized text.
+The right panel sets `scrollbar-background`, `scrollbar-color`, and `scrollbar-corner-color`, and the left panel shows the default colors for comparison.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/scrollbars.py"}
+    ```
+
+=== "scrollbars.py"
+
+    ```python
+    --8<-- "docs/examples/styles/scrollbars.py"
+    ```
+
+=== "scrollbars.css"
+
+    ```css
+    --8<-- "docs/examples/styles/scrollbars.css"
+    ```
diff --git a/docs/styles/scrollbar_colors/scrollbar_background.md b/docs/styles/scrollbar_colors/scrollbar_background.md
new file mode 100644
index 0000000000..e2792c67e2
--- /dev/null
+++ b/docs/styles/scrollbar_colors/scrollbar_background.md
@@ -0,0 +1,55 @@
+# Scrollbar-background
+
+The `scrollbar-background` sets the background color of the scrollbar.
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./scrollbar_background">scrollbar-background</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`scrollbar-background` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the background color of a scrollbar.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+=== "Output"
+
+    ![](scrollbar_colors_demo.gif)
+
+    !!! note
+
+        The GIF above has reduced quality to make it easier to load in the documentation.
+        Try running the example yourself with `textual run docs/examples/styles/scrollbars2.py`.
+
+=== "scrollbars2.py"
+
+    ```py
+    --8<-- "docs/examples/styles/scrollbars2.py"
+    ```
+
+=== "scrollbars2.css"
+
+    ```css hl_lines="2"
+    --8<-- "docs/examples/styles/scrollbars2.css"
+    ```
+
+## CSS
+
+```css
+scrollbar-backround: blue;
+```
+
+## Python
+
+```py
+widget.styles.scrollbar_background = "blue"
+```
diff --git a/docs/styles/scrollbar_colors/scrollbar_background_active.md b/docs/styles/scrollbar_colors/scrollbar_background_active.md
new file mode 100644
index 0000000000..2652418ee1
--- /dev/null
+++ b/docs/styles/scrollbar_colors/scrollbar_background_active.md
@@ -0,0 +1,56 @@
+# Scrollbar-background-active
+
+The `scrollbar-background-active` sets the background color of the scrollbar when the thumb is being dragged.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./scrollbar_background_active">scrollbar-background-active</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`scrollbar-background-active` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the background color of a scrollbar when its thumb is being dragged.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+=== "Output"
+
+    ![](scrollbar_colors_demo.gif)
+
+    !!! note
+
+        The GIF above has reduced quality to make it easier to load in the documentation.
+        Try running the example yourself with `textual run docs/examples/styles/scrollbars2.py`.
+
+=== "scrollbars2.py"
+
+    ```py
+    --8<-- "docs/examples/styles/scrollbars2.py"
+    ```
+
+=== "scrollbars2.css"
+
+    ```css hl_lines="3"
+    --8<-- "docs/examples/styles/scrollbars2.css"
+    ```
+
+## CSS
+
+```css
+scrollbar-backround-active: red;
+```
+
+## Python
+
+```py
+widget.styles.scrollbar_background_active = "red"
+```
diff --git a/docs/styles/scrollbar_colors/scrollbar_background_hover.md b/docs/styles/scrollbar_colors/scrollbar_background_hover.md
new file mode 100644
index 0000000000..b01ebe1b9f
--- /dev/null
+++ b/docs/styles/scrollbar_colors/scrollbar_background_hover.md
@@ -0,0 +1,56 @@
+# Scrollbar-background-hover
+
+The `scrollbar-background-hover` sets the background color of the scrollbar when the cursor is over it.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./scrollbar_background_hover">scrollbar-background-hover</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`scrollbar-background-hover` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the background color of a scrollbar when the cursor is over it.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+=== "Output"
+
+    ![](scrollbar_colors_demo.gif)
+
+    !!! note
+
+        The GIF above has reduced quality to make it easier to load in the documentation.
+        Try running the example yourself with `textual run docs/examples/styles/scrollbars2.py`.
+
+=== "scrollbars2.py"
+
+    ```py
+    --8<-- "docs/examples/styles/scrollbars2.py"
+    ```
+
+=== "scrollbars2.css"
+
+    ```css hl_lines="4"
+    --8<-- "docs/examples/styles/scrollbars2.css"
+    ```
+
+## CSS
+
+```css
+scrollbar-background-hover: purple;
+```
+
+## Python
+
+```py
+widget.styles.scrollbar_background_hover = "purple"
+```
diff --git a/docs/styles/scrollbar_colors/scrollbar_color.md b/docs/styles/scrollbar_colors/scrollbar_color.md
new file mode 100644
index 0000000000..421e676610
--- /dev/null
+++ b/docs/styles/scrollbar_colors/scrollbar_color.md
@@ -0,0 +1,56 @@
+# Scrollbar-color
+
+The `scrollbar-color` sets the color of the scrollbar.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./scrollbar_color">scrollbar-color</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`scrollbar-color` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the color of a scrollbar.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+=== "Output"
+
+    ![](scrollbar_colors_demo.gif)
+
+    !!! note
+
+        The GIF above has reduced quality to make it easier to load in the documentation.
+        Try running the example yourself with `textual run docs/examples/styles/scrollbars2.py`.
+
+=== "scrollbars2.py"
+
+    ```py
+    --8<-- "docs/examples/styles/scrollbars2.py"
+    ```
+
+=== "scrollbars2.css"
+
+    ```css hl_lines="5"
+    --8<-- "docs/examples/styles/scrollbars2.css"
+    ```
+
+## CSS
+
+```css
+scrollbar-color: cyan;
+```
+
+## Python
+
+```py
+widget.styles.scrollbar_color = "cyan"
+```
diff --git a/docs/styles/scrollbar_colors/scrollbar_color_active.md b/docs/styles/scrollbar_colors/scrollbar_color_active.md
new file mode 100644
index 0000000000..6767790ff2
--- /dev/null
+++ b/docs/styles/scrollbar_colors/scrollbar_color_active.md
@@ -0,0 +1,56 @@
+# Scrollbar-color-active
+
+The `scrollbar-color-active` sets the color of the scrollbar when the thumb is being dragged.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./scrollbar_color_active">scrollbar-color-active</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`scrollbar-color-active` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the color of a scrollbar when its thumb is being dragged.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+=== "Output"
+
+    ![](scrollbar_colors_demo.gif)
+
+    !!! note
+
+        The GIF above has reduced quality to make it easier to load in the documentation.
+        Try running the example yourself with `textual run docs/examples/styles/scrollbars2.py`.
+
+=== "scrollbars2.py"
+
+    ```py
+    --8<-- "docs/examples/styles/scrollbars2.py"
+    ```
+
+=== "scrollbars2.css"
+
+    ```css hl_lines="6"
+    --8<-- "docs/examples/styles/scrollbars2.css"
+    ```
+
+## CSS
+
+```css
+scrollbar-color-active: yellow;
+```
+
+## Python
+
+```py
+widget.styles.scrollbar_color_active = "yellow"
+```
diff --git a/docs/styles/scrollbar_colors/scrollbar_color_hover.md b/docs/styles/scrollbar_colors/scrollbar_color_hover.md
new file mode 100644
index 0000000000..3005d0da14
--- /dev/null
+++ b/docs/styles/scrollbar_colors/scrollbar_color_hover.md
@@ -0,0 +1,56 @@
+# Scrollbar-color-hover
+
+The `scrollbar-color-hover` sets the color of the scrollbar when the cursor is over it.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./scrollbar_color_hover">scrollbar-color-hover</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`scrollbar-color-hover` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the color of a scrollbar when the cursor is over it.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+=== "Output"
+
+    ![](scrollbar_colors_demo.gif)
+
+    !!! note
+
+        The GIF above has reduced quality to make it easier to load in the documentation.
+        Try running the example yourself with `textual run docs/examples/styles/scrollbars2.py`.
+
+=== "scrollbars2.py"
+
+    ```py
+    --8<-- "docs/examples/styles/scrollbars2.py"
+    ```
+
+=== "scrollbars2.css"
+
+    ```css hl_lines="7"
+    --8<-- "docs/examples/styles/scrollbars2.css"
+    ```
+
+## CSS
+
+```css
+scrollbar-color-hover: pink;
+```
+
+## Python
+
+```py
+widget.styles.scrollbar_color_hover = "pink"
+```
diff --git a/docs/styles/scrollbar_colors/scrollbar_colors_demo.gif b/docs/styles/scrollbar_colors/scrollbar_colors_demo.gif
new file mode 100644
index 0000000000..b78a05afe2
Binary files /dev/null and b/docs/styles/scrollbar_colors/scrollbar_colors_demo.gif differ
diff --git a/docs/styles/scrollbar_colors/scrollbar_corner_color.md b/docs/styles/scrollbar_colors/scrollbar_corner_color.md
new file mode 100644
index 0000000000..4edc582d4d
--- /dev/null
+++ b/docs/styles/scrollbar_colors/scrollbar_corner_color.md
@@ -0,0 +1,54 @@
+# Scrollbar-corner-color
+
+The `scrollbar-corner-color` sets the color of the gap between the horizontal and vertical scrollbars.
+
+## Syntax
+
+--8<-- "docs/snippets/syntax_block_start.md"
+<a href="./scrollbar_corner_color">scrollbar-corner-color</a>: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
+--8<-- "docs/snippets/syntax_block_end.md"
+
+`scrollbar-corner-color` accepts a [`<color>`](../../../css_types/color) (with an optional transparency level defined by a [`<percentage>`](../../../css_types/percentage)) that is used to define the color of the gap between the horizontal and vertical scrollbars of a widget.
+
+### Values
+
+#### &lt;color&gt;
+
+--8<-- "docs/snippets/type_syntax/color.md"
+
+#### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+
+## Example
+
+The example below sets the scrollbar corner (bottom-right corner of the screen) to white.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/scrollbar_corner_color.py" lines=5}
+    ```
+
+=== "scrollbar_corner_color.py"
+
+    ```py
+    --8<-- "docs/examples/styles/scrollbar_corner_color.py"
+    ```
+
+=== "scrollbar_corner_color.css"
+
+    ```css hl_lines="3"
+    --8<-- "docs/examples/styles/scrollbar_corner_color.css"
+    ```
+
+## CSS
+
+```css
+scrollbar-corner-color: white;
+```
+
+## Python
+
+```py
+widget.styles.scrollbar_corner_color = "white"
+```
diff --git a/docs/styles/scrollbar_gutter.md b/docs/styles/scrollbar_gutter.md
index 7c2ed5e443..c08ac4e2de 100644
--- a/docs/styles/scrollbar_gutter.md
+++ b/docs/styles/scrollbar_gutter.md
@@ -1,27 +1,32 @@
 # Scrollbar-gutter
 
-The `scrollbar-gutter` rule allows authors to reserve space for the vertical scrollbar.
-
-Setting the value to `stable` prevents unwanted layout changes when the scrollbar becomes visible.
+The `scrollbar-gutter` rule allows reserving space for a vertical scrollbar.
 
 ## Syntax
 
-```
-scrollbar-gutter: [auto|stable];
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+scrollbar-gutter: auto | stable;
+--8<-- "docs/snippets/syntax_block_end.md"
 
 ### Values
 
-| Value            | Description                                      |
-|------------------|--------------------------------------------------|
-| `auto` (default) | No space is reserved for the vertical scrollbar. |
-| `stable`         | Space is reserved for the vertical scrollbar.    |
+| Value            | Description                                    |
+|------------------|------------------------------------------------|
+| `auto` (default) | No space is reserved for a vertical scrollbar. |
+| `stable`         | Space is reserved for a vertical scrollbar.    |
+
+Setting the value to `stable` prevents unwanted layout changes when the scrollbar becomes visible, whereas the default value of `auto` means that the layout of your application is recomputed when a vertical scrollbar becomes needed.
 
 ## Example
 
 In the example below, notice the gap reserved for the scrollbar on the right side of the
 terminal window.
 
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/scrollbar_gutter.py"}
+    ```
+
 === "scrollbar_gutter.py"
 
     ```python
@@ -30,24 +35,20 @@ terminal window.
 
 === "scrollbar_gutter.css"
 
-    ```scss
+    ```scss hl_lines="2"
     --8<-- "docs/examples/styles/scrollbar_gutter.css"
     ```
 
-=== "Output"
-
-    ```{.textual path="docs/examples/styles/scrollbar_gutter.py"}
-    ```
-
 ## CSS
 
 ```sass
-/* Reserve space for vertical scrollbar */
-scrollbar-gutter: stable;
+scrollbar-gutter: auto;    /* Don't reserve space for a vertical scrollbar. */
+scrollbar-gutter: stable;  /* Reserve space for a vertical scrollbar. */
 ```
 
 ## Python
 
 ```python
-self.styles.scrollbar_gutter = "stable"
+self.styles.scrollbar_gutter = "auto"    # Don't reserve space for a vertical scrollbar.
+self.styles.scrollbar_gutter = "stable"  # Reserve space for a vertical scrollbar.
 ```
diff --git a/docs/styles/scrollbar_size.md b/docs/styles/scrollbar_size.md
index ccc9c5e803..19c0929711 100644
--- a/docs/styles/scrollbar_size.md
+++ b/docs/styles/scrollbar_size.md
@@ -1,19 +1,31 @@
 # Scrollbar-size
 
-The `scrollbar-size` rule changes the size of the scrollbars. It takes 2 integers for horizontal and vertical scrollbar size respectively.
-
-The scrollbar dimensions may also be set individually with `scrollbar-size-horizontal` and `scrollbar-size-vertical`.
+The `scrollbar-size` rule defines the width of the scrollbars.
 
 ## Syntax
 
-```
-scrollbar-size: <INTEGER> <INTEGER>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+scrollbar-size: <a href="../../css_types/integer">&lt;integer&gt;</a> <a href="../../css_types/integer">&lt;integer&gt;</a>;
+              # horizontal vertical
+
+scrollbar-size-horizontal: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+scrollbar-size-vertical: <a href="../../css_types/integer">&lt;integer&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The `scrollbar-size` rule takes two [`<integer>`](../css_types/integer.md) to set the horizontal and vertical scrollbar sizes, respectively.
+This customisable size is the width of the scrollbar, given that its length will always be 100% of the container.
+
+The scrollbar widths may also be set individually with `scrollbar-size-horizontal` and `scrollbar-size-vertical`.
 
-## Example
+## Examples
 
 In this example we modify the size of the widget's scrollbar to be _much_ larger than usual.
 
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/scrollbar_size.py"}
+    ```
+
 === "scrollbar_size.py"
 
     ```python
@@ -22,28 +34,50 @@ In this example we modify the size of the widget's scrollbar to be _much_ larger
 
 === "scrollbar_size.css"
 
-    ```css
+    ```css hl_lines="13"
     --8<-- "docs/examples/styles/scrollbar_size.css"
     ```
 
+In the next example we show three containers with differently sized scrollbars.
+
 === "Output"
 
-    ```{.textual path="docs/examples/styles/scrollbar_size.py"}
+    ```{.textual path="docs/examples/styles/scrollbar_size2.py"}
+    ```
+
+=== "scrollbar_size2.py"
+
+    ```python
+    --8<-- "docs/examples/styles/scrollbar_size2.py"
+    ```
+
+=== "scrollbar_size2.css"
+
+    ```css hl_lines="6 11 16"
+    --8<-- "docs/examples/styles/scrollbar_size2.css"
     ```
 
 ## CSS
 
 ```sass
 /* Set horizontal scrollbar to 10, and vertical scrollbar to 4 */
-Widget {
-    scrollbar-size: 10 4;
-}
+scrollbar-size: 10 4;
+
+/* Set horizontal scrollbar to 10 */
+scrollbar-size-horizontal: 10;
+
+/* Set vertical scrollbar to 4 */
+scrollbar-size-vertical: 4;
 ```
 
 ## Python
 
-```python
-# Set horizontal scrollbar to 10, and vertical scrollbar to 4
-widget.styles.horizontal_scrollbar = 10
-widget.styles.vertical_scrollbar = 10
+The rule `scrollbar-size` has no Python equivalent.
+The scrollbar sizes must be set independently:
+
+```py
+# Set horizontal scrollbar to 10:
+widget.styles.scrollbar_size_horizontal = 10
+# Set vertical scrollbar to 4:
+widget.styles.scrollbar_size_vertical = 4
 ```
diff --git a/docs/styles/text_align.md b/docs/styles/text_align.md
index 1fc9b515c8..dc55dc03e8 100644
--- a/docs/styles/text_align.md
+++ b/docs/styles/text_align.md
@@ -1,28 +1,32 @@
 # Text-align
 
-The `text-align` rule aligns text within a widget.
+The `text-align` rule sets the text alignment in a widget.
 
 ## Syntax
 
-```
-text-align: [left|start|center|right|end|justify];
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+text-align: <a href="../../css_types/text_align">&lt;text-align&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The `text-align` rule accepts a value of the type [`<text-align>`](../css_types/text_align.md) that defines how text is aligned inside the widget.
 
 ### Values
 
-| Value     | Description                      |
-|-----------|----------------------------------|
-| `left`    | Left aligns text in the widget   |
-| `start`   | Left aligns text in the widget   |
-| `center`  | Center aligns text in the widget |
-| `right`   | Right aligns text in the widget  |
-| `end`     | Right aligns text in the widget  |
-| `justify` | Justifies text in the widget     |
+--8<-- "docs/snippets/type_syntax/text_align.md"
+
+### Defaults
+
+The default value is `start`.
 
 ## Example
 
 This example shows, from top to bottom: `left`, `center`, `right`, and `justify` text alignments.
 
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/text_align.py"}
+    ```
+
 === "text_align.py"
 
     ```python
@@ -31,22 +35,17 @@ This example shows, from top to bottom: `left`, `center`, `right`, and `justify`
 
 === "text_align.css"
 
-    ```css
+    ```css hl_lines="2 7 12 17"
     --8<-- "docs/examples/styles/text_align.css"
     ```
 
-=== "Output"
-
-    ```{.textual path="docs/examples/styles/text_align.py"}
-    ```
+[//]: # (TODO: Add an example that shows how `start` and `end` change when RTL support is added.)
 
 ## CSS
 
 ```sass
-/* Set text in all Widgets to be right aligned */
-Widget {
-    text-align: right;
-}
+/* Set text in the widget to be right aligned */
+text-align: right;
 ```
 
 ## Python
diff --git a/docs/styles/text_opacity.md b/docs/styles/text_opacity.md
index 5a0e1c6c5b..b7b8f63ff1 100644
--- a/docs/styles/text_opacity.md
+++ b/docs/styles/text_opacity.md
@@ -4,20 +4,35 @@ The `text-opacity` blends the color of the content of a widget with the color of
 
 ## Syntax
 
-```
-text-opacity: <FRACTIONAL>;
-```
+--8<-- "docs/snippets/syntax_block_start.md"
+text-opacity: <a href="../../css_types/number">&lt;number&gt;</a> | <a href="../../css_types/percentage">&lt;percentage&gt;</a>;
+--8<-- "docs/snippets/syntax_block_end.md"
+
+The text opacity can be set as a [`<number>`](../css_types/number.md) or a [`<percentage>`](../css_types/percentage.md).
+`0`/`0%` means no opacity, which is equivalent to full transparency.
+Conversely, `1`/`100%` means full opacity, which is equivalent to no transparency.
+Values outside of these ranges will be clamped.
 
 ### Values
 
-As a fractional property, `text-opacity` can be set to either a float (between 0 and 1),
-or a percentage, e.g. `45%`.
-Float values will be clamped between 0 and 1.
-Percentage values will be clamped between 0% and 100%.
+### &lt;number&gt;
+
+--8<-- "docs/snippets/type_syntax/number.md"
+The value of [`<number>`](../../css_types/number) is clamped between `0` and `1`.
+
+### &lt;percentage&gt;
+
+--8<-- "docs/snippets/type_syntax/percentage.md"
+The value of [`<percentage>`](../../css_types/percentage) is clamped between `0%` and `100%`.
 
 ## Example
 
-This example shows, from top to bottom, increasing text-opacity values.
+This example shows, from top to bottom, increasing `text-opacity` values.
+
+=== "Output"
+
+    ```{.textual path="docs/examples/styles/text_opacity.py"}
+    ```
 
 === "text_opacity.py"
 
@@ -31,18 +46,11 @@ This example shows, from top to bottom, increasing text-opacity values.
     --8<-- "docs/examples/styles/text_opacity.css"
     ```
 
-=== "Output"
-
-    ```{.textual path="docs/examples/styles/text_opacity.py"}
-    ```
-
 ## CSS
 
 ```sass
 /* Set the text to be "half-faded" against the background of the widget */
-Widget {
-    text-opacity: 50%;
-}
+text-opacity: 50%;
 ```
 
 ## Python
diff --git a/mkdocs.yml b/mkdocs.yml
index 7f73787b38..fffeef3c08 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -28,6 +28,20 @@ nav:
   - "roadmap.md"
   - Reference:
     - "reference/index.md"
+    - CSS Types:
+      - "css_types/index.md"
+      - "css_types/border.md"
+      - "css_types/color.md"
+      - "css_types/horizontal.md"
+      - "css_types/integer.md"
+      - "css_types/name.md"
+      - "css_types/number.md"
+      - "css_types/overflow.md"
+      - "css_types/percentage.md"
+      - "css_types/scalar.md"
+      - "css_types/text_align.md"
+      - "css_types/text_style.md"
+      - "css_types/vertical.md"
     - Events:
       - "events/index.md"
       - "events/blur.md"
@@ -63,12 +77,26 @@ nav:
       - "styles/content_align.md"
       - "styles/display.md"
       - "styles/dock.md"
-      - "styles/grid.md"
+      - Grid:
+        - "styles/grid/index.md"
+        - "styles/grid/grid_size.md"
+        - "styles/grid/grid_rows.md"
+        - "styles/grid/grid_columns.md"
+        - "styles/grid/grid_gutter.md"
+        - "styles/grid/row_span.md"
+        - "styles/grid/column_span.md"
       - "styles/height.md"
       - "styles/layer.md"
       - "styles/layers.md"
       - "styles/layout.md"
-      - "styles/links.md"
+      - Links:
+        - "styles/links/index.md"
+        - "styles/links/link_color.md"
+        - "styles/links/link_background.md"
+        - "styles/links/link_style.md"
+        - "styles/links/link_hover_color.md"
+        - "styles/links/link_hover_background.md"
+        - "styles/links/link_hover_style.md"
       - "styles/margin.md"
       - "styles/max_height.md"
       - "styles/max_width.md"
@@ -79,12 +107,20 @@ nav:
       - "styles/outline.md"
       - "styles/overflow.md"
       - "styles/padding.md"
-      - "styles/scrollbar.md"
+      - Scrollbar colors:
+        - "styles/scrollbar_colors/index.md"
+        - "styles/scrollbar_colors/scrollbar_background.md"
+        - "styles/scrollbar_colors/scrollbar_background_active.md"
+        - "styles/scrollbar_colors/scrollbar_background_hover.md"
+        - "styles/scrollbar_colors/scrollbar_color.md"
+        - "styles/scrollbar_colors/scrollbar_color_active.md"
+        - "styles/scrollbar_colors/scrollbar_color_hover.md"
+        - "styles/scrollbar_colors/scrollbar_corner_color.md"
       - "styles/scrollbar_gutter.md"
       - "styles/scrollbar_size.md"
       - "styles/text_align.md"
-      - "styles/text_style.md"
       - "styles/text_opacity.md"
+      - "styles/text_style.md"
       - "styles/tint.md"
       - "styles/visibility.md"
       - "styles/width.md"
diff --git a/src/textual/color.py b/src/textual/color.py
index a53a0abafc..f51eabbaab 100644
--- a/src/textual/color.py
+++ b/src/textual/color.py
@@ -386,25 +386,29 @@ def parse(cls, color_text: str | Color) -> Color:
 
         Colors may be parsed from the following formats:
 
-        Text beginning with a `#` is parsed as hex:
+        - Text beginning with a `#` is parsed as a hexadecimal color code,
+         where R, G, B, and A must be hexadecimal digits (0-9A-F):
 
-        R, G, and B must be hex digits (0-9A-F)
+            - `#RGB`
+            - `#RGBA`
+            - `#RRGGBB`
+            - `#RRGGBBAA`
 
-        - `#RGB`
-        - `#RRGGBB`
-        - `#RRGGBBAA`
+        - Alternatively, RGB colors can also be specified in the format
+         that follows, where R, G, and B must be numbers between 0 and 255
+         and A must be a value between 0 and 1:
 
-        Text in the following formats is parsed as decimal values:
+            - `rgb(R,G,B)`
+            - `rgb(R,G,B,A)`
 
-        RED, GREEN, and BLUE must be numbers between 0 and 255.
-        ALPHA should ba a value between 0 and 1.
+        - The HSL model can also be used, with a syntax similar to the above,
+         if H is a value between 0 and 360, S and L are percentages, and A
+         is a value between 0 and 1:
 
-        - `rgb(RED,GREEN,BLUE)`
-        - `rgba(RED,GREEN,BLUE,ALPHA)`
-        - `hsl(RED,GREEN,BLUE)`
-        - `hsla(RED,GREEN,BLUE,ALPHA)`
+            - `hsl(H,S,L)`
+            - `hsla(H,S,L,A)`
 
-        All other text will raise a `ColorParseError`.
+        Any other formats will raise a `ColorParseError`.
 
         Args:
             color_text (str | Color): Text with a valid color format. Color objects will
@@ -414,7 +418,7 @@ def parse(cls, color_text: str | Color) -> Color:
             ColorParseError: If the color is not encoded correctly.
 
         Returns:
-            Color: New color object.
+            Color: Instance encoding the color specified by the argument.
         """
         if isinstance(color_text, Color):
             return color_text


Code review comments:
diff_hunk: @@ -0,0 +1,59 @@
+# &lt;border&gt;
+
+The `<border>` CSS type represents a border style.
+
+## Syntax
+
+--8<-- "docs/snippets/type_syntax/border.md"
+
+## Border command
+
+The `textual` CLI has a subcommand which will let you explore the various border types interactively, when applied to the CSS rule [`border`](../styles/border.md):
+
+```
+textual borders
+```
+
+## Examples
+
+### CSS
+
+```sass
+* {
+    rule: ascii   /* A border with plus, hyphen, and vertical bar characters. */
path: docs/css_types/border.md
text: @user1:
I guess the `rule` is meant as a placeholder?

This doesn't really serve as an example, since it is invalid CSS.

I think what we need from the examples section is just a few examples of use so the reader can orient themselves. Doesn't have to be an exhaustive list, which is covered nicely in the Syntax section.

Suggest small fragments. For the border something like this:

```sass
#container {
    border: heavy red;
}

#heading {
    border-bottom: solid blue;
}
```

Something similar for the Python section.

@author:
Fixed in 81ddae7

diff_hunk: @@ -0,0 +1,9 @@
+The legal values for a [`<color>`](/css_types/color) depend on the [class `Color`][textual.color.Color] and include:
+
+ - a recognised [named color](../../api/color#textual.color--named-colors) (e.g., `red`);
+ - a hexadecimal number representing the RGB values of the color (e.g., `#F35573`);
+ - a color description in the RGB system (e.g., `rgb(23,78,200)`);
+ - a color description in the HSL system (e.g., `hsl(290,70%,80%)`); and
+
+For more details about the exact formats accepted, see [the class method `Color.parse`][textual.color.Color.parse].
path: docs/snippets/type_syntax/color.md
text: @user1:
I think this page should be exhaustive regarding the color formats. Since we're talking about CSS, I don't think we should direct people to the code reference.

@author:
Fixed in 1ef20eb.

diff_hunk: @@ -0,0 +1,9 @@
+The legal values for a [`<color>`](/css_types/color) depend on the [class `Color`][textual.color.Color] and include:
path: docs/snippets/type_syntax/color.md
text: @user1:
I don't think we need the reference to the Color class here.

```suggestion
A [`<color>`](/css_types/color) should be in one of the following formats:
```



@author:
Fixed in 1ef20eb.

Is it worth adding a formal syntax description of the values accepted, much like we have for the styles?
Something like

```
color: named-color
     | hex-rgb
     | functional-rgb
     | functional-hsl

hex-rgb: # hex{3}
       | # hex{4}
       | # hex{6}
       | # hex{8}
...
```