Repository: Textualize/textual

Issue:
[BUG] Header's title text isn't centered properly 
> Please give a brief but clear explanation of what the issue is. Let us know what the behaviour you expect is, and what is actually happening. Let us know what operating system you are running on, and what terminal you are using.

`Header`'s title text isn't centered, `show_clock=True` exacerbates the issue. My expectation is that the title is centered within the visible space between the icon/clock (if shown), and between the icon/right edge if not.

> Feel free to add screenshots and/or videos. These can be very helpful!

![image](https://user-images.githubusercontent.com/43392618/198884075-bc981a9b-f41c-4501-86d6-ebe0595656d1.png)

![image](https://user-images.githubusercontent.com/43392618/198884090-6561b9d0-ba38-4ec0-9aa0-775c0b9ab9d1.png)

![image](https://user-images.githubusercontent.com/43392618/198884124-ad6cb347-951d-47ed-8920-d4ad2da762af.png)

> If you can, include a complete working example that demonstrates the bug. Please check it can run without modifications.

```python
from textual.app import App, ComposeResult
from textual.widgets import Header, Static

class Demo(App):
    TITLE = "Demonstration"
    CSS = """
    Screen {
        layout: grid;
        grid-size: 2;
    }
    .box {
        height: 100%;
        border: white;
    }
    """

    def compose(self) -> ComposeResult:
        yield Header(show_clock=True)
        yield Static(classes="box")
        yield Static(classes="box")
```


Discussion:
Confirmed, good catch. Should be a nice easy fix. :-)

Resolving patch:
diff --git a/src/textual/widgets/_header.py b/src/textual/widgets/_header.py
--- a/src/textual/widgets/_header.py
+++ b/src/textual/widgets/_header.py
@@ -25,14 +25,26 @@ def render(self):
         return self.icon
 
 
-class HeaderClock(Widget):
-    """Display a clock on the right of the header."""
+class HeaderClockSpace(Widget):
+    """The space taken up by the clock on the right of the header."""
 
     DEFAULT_CSS = """
-    HeaderClock {
+    HeaderClockSpace {
         dock: right;
         width: 10;
         padding: 0 1;
+    }
+    """
+
+    def render(self) -> str:
+        return ""
+
+
+class HeaderClock(HeaderClockSpace):
+    """Display a clock on the right of the header."""
+
+    DEFAULT_CSS = """
+    HeaderClock {
         background: $secondary-background-lighten-1;
         color: $text;
         text-opacity: 85%;
@@ -54,7 +66,6 @@ class HeaderTitle(Widget):
     HeaderTitle {
         content-align: center middle;
         width: 100%;
-        margin-right: 10;
     }
     """
 
@@ -107,8 +118,7 @@ def __init__(
     def compose(self):
         yield HeaderIcon()
         yield HeaderTitle()
-        if self.show_clock:
-            yield HeaderClock()
+        yield HeaderClock() if self.show_clock else HeaderClockSpace()
 
     def watch_tall(self, tall: bool) -> None:
         self.set_class(tall, "-tall")


Test patch:
diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
--- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
+++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
@@ -5404,132 +5404,132 @@
           font-weight: 700;
       }
   
-      .terminal-1853139379-matrix {
+      .terminal-2939949418-matrix {
           font-family: Fira Code, monospace;
           font-size: 20px;
           line-height: 24.4px;
           font-variant-east-asian: full-width;
       }
   
-      .terminal-1853139379-title {
+      .terminal-2939949418-title {
           font-size: 18px;
           font-weight: bold;
           font-family: arial;
       }
   
-      .terminal-1853139379-r1 { fill: #c5c8c6 }
-  .terminal-1853139379-r2 { fill: #e8e7e5 }
-  .terminal-1853139379-r3 { fill: #e1e1e1 }
+      .terminal-2939949418-r1 { fill: #c5c8c6 }
+  .terminal-2939949418-r2 { fill: #e8e7e5 }
+  .terminal-2939949418-r3 { fill: #e1e1e1 }
       </style>
   
       <defs>
-      <clipPath id="terminal-1853139379-clip-terminal">
+      <clipPath id="terminal-2939949418-clip-terminal">
         <rect x="0" y="0" width="975.0" height="584.5999999999999" />
       </clipPath>
-      <clipPath id="terminal-1853139379-line-0">
+      <clipPath id="terminal-2939949418-line-0">
       <rect x="0" y="1.5" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-1">
+  <clipPath id="terminal-2939949418-line-1">
       <rect x="0" y="25.9" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-2">
+  <clipPath id="terminal-2939949418-line-2">
       <rect x="0" y="50.3" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-3">
+  <clipPath id="terminal-2939949418-line-3">
       <rect x="0" y="74.7" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-4">
+  <clipPath id="terminal-2939949418-line-4">
       <rect x="0" y="99.1" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-5">
+  <clipPath id="terminal-2939949418-line-5">
       <rect x="0" y="123.5" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-6">
+  <clipPath id="terminal-2939949418-line-6">
       <rect x="0" y="147.9" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-7">
+  <clipPath id="terminal-2939949418-line-7">
       <rect x="0" y="172.3" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-8">
+  <clipPath id="terminal-2939949418-line-8">
       <rect x="0" y="196.7" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-9">
+  <clipPath id="terminal-2939949418-line-9">
       <rect x="0" y="221.1" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-10">
+  <clipPath id="terminal-2939949418-line-10">
       <rect x="0" y="245.5" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-11">
+  <clipPath id="terminal-2939949418-line-11">
       <rect x="0" y="269.9" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-12">
+  <clipPath id="terminal-2939949418-line-12">
       <rect x="0" y="294.3" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-13">
+  <clipPath id="terminal-2939949418-line-13">
       <rect x="0" y="318.7" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-14">
+  <clipPath id="terminal-2939949418-line-14">
       <rect x="0" y="343.1" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-15">
+  <clipPath id="terminal-2939949418-line-15">
       <rect x="0" y="367.5" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-16">
+  <clipPath id="terminal-2939949418-line-16">
       <rect x="0" y="391.9" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-17">
+  <clipPath id="terminal-2939949418-line-17">
       <rect x="0" y="416.3" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-18">
+  <clipPath id="terminal-2939949418-line-18">
       <rect x="0" y="440.7" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-19">
+  <clipPath id="terminal-2939949418-line-19">
       <rect x="0" y="465.1" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-20">
+  <clipPath id="terminal-2939949418-line-20">
       <rect x="0" y="489.5" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-21">
+  <clipPath id="terminal-2939949418-line-21">
       <rect x="0" y="513.9" width="976" height="24.65"/>
               </clipPath>
-  <clipPath id="terminal-1853139379-line-22">
+  <clipPath id="terminal-2939949418-line-22">
       <rect x="0" y="538.3" width="976" height="24.65"/>
               </clipPath>
       </defs>
   
-      <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="633.6" rx="8"/><text class="terminal-1853139379-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">HeaderApp</text>
+      <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="633.6" rx="8"/><text class="terminal-2939949418-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">HeaderApp</text>
               <g transform="translate(26,22)">
               <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
               <circle cx="22" cy="0" r="7" fill="#febc2e"/>
               <circle cx="44" cy="0" r="7" fill="#28c840"/>
               </g>
           
-      <g transform="translate(9, 41)" clip-path="url(#terminal-1853139379-clip-terminal)">
-      <rect fill="#534838" x="0" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="12.2" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="24.4" y="1.5" width="73.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="97.6" y="1.5" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="414.8" y="1.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="524.6" y="1.5" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="854" y="1.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="25.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="50.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="74.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="221.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="343.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="367.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="416.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="465.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="513.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="562.7" width="976" height="24.65" shape-rendering="crispEdges"/>
-      <g class="terminal-1853139379-matrix">
-      <text class="terminal-1853139379-r2" x="12.2" y="20" textLength="12.2" clip-path="url(#terminal-1853139379-line-0)">⭘</text><text class="terminal-1853139379-r2" x="414.8" y="20" textLength="109.8" clip-path="url(#terminal-1853139379-line-0)">HeaderApp</text><text class="terminal-1853139379-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1853139379-line-0)">
-  </text><text class="terminal-1853139379-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1853139379-line-1)">
-  </text><text class="terminal-1853139379-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1853139379-line-2)">
-  </text><text class="terminal-1853139379-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1853139379-line-3)">
-  </text><text class="terminal-1853139379-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1853139379-line-4)">
-  </text><text class="terminal-1853139379-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1853139379-line-5)">
-  </text><text class="terminal-1853139379-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1853139379-line-6)">
-  </text><text class="terminal-1853139379-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1853139379-line-7)">
-  </text><text class="terminal-1853139379-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1853139379-line-8)">
-  </text><text class="terminal-1853139379-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1853139379-line-9)">
-  </text><text class="terminal-1853139379-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1853139379-line-10)">
-  </text><text class="terminal-1853139379-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1853139379-line-11)">
-  </text><text class="terminal-1853139379-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1853139379-line-12)">
-  </text><text class="terminal-1853139379-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1853139379-line-13)">
-  </text><text class="terminal-1853139379-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1853139379-line-14)">
-  </text><text class="terminal-1853139379-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1853139379-line-15)">
-  </text><text class="terminal-1853139379-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1853139379-line-16)">
-  </text><text class="terminal-1853139379-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1853139379-line-17)">
-  </text><text class="terminal-1853139379-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1853139379-line-18)">
-  </text><text class="terminal-1853139379-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-1853139379-line-19)">
-  </text><text class="terminal-1853139379-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-1853139379-line-20)">
-  </text><text class="terminal-1853139379-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-1853139379-line-21)">
-  </text><text class="terminal-1853139379-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-1853139379-line-22)">
+      <g transform="translate(9, 41)" clip-path="url(#terminal-2939949418-clip-terminal)">
+      <rect fill="#534838" x="0" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="12.2" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="24.4" y="1.5" width="73.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="97.6" y="1.5" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="414.8" y="1.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="524.6" y="1.5" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="854" y="1.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="866.2" y="1.5" width="0" height="24.65" shape-rendering="crispEdges"/><rect fill="#534838" x="866.2" y="1.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="25.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="50.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="74.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="221.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="343.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="367.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="416.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="465.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="513.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="562.7" width="976" height="24.65" shape-rendering="crispEdges"/>
+      <g class="terminal-2939949418-matrix">
+      <text class="terminal-2939949418-r2" x="12.2" y="20" textLength="12.2" clip-path="url(#terminal-2939949418-line-0)">⭘</text><text class="terminal-2939949418-r2" x="414.8" y="20" textLength="109.8" clip-path="url(#terminal-2939949418-line-0)">HeaderApp</text><text class="terminal-2939949418-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-2939949418-line-0)">
+  </text><text class="terminal-2939949418-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-2939949418-line-1)">
+  </text><text class="terminal-2939949418-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-2939949418-line-2)">
+  </text><text class="terminal-2939949418-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-2939949418-line-3)">
+  </text><text class="terminal-2939949418-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-2939949418-line-4)">
+  </text><text class="terminal-2939949418-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-2939949418-line-5)">
+  </text><text class="terminal-2939949418-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-2939949418-line-6)">
+  </text><text class="terminal-2939949418-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-2939949418-line-7)">
+  </text><text class="terminal-2939949418-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-2939949418-line-8)">
+  </text><text class="terminal-2939949418-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-2939949418-line-9)">
+  </text><text class="terminal-2939949418-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-2939949418-line-10)">
+  </text><text class="terminal-2939949418-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-2939949418-line-11)">
+  </text><text class="terminal-2939949418-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-2939949418-line-12)">
+  </text><text class="terminal-2939949418-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-2939949418-line-13)">
+  </text><text class="terminal-2939949418-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-2939949418-line-14)">
+  </text><text class="terminal-2939949418-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-2939949418-line-15)">
+  </text><text class="terminal-2939949418-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-2939949418-line-16)">
+  </text><text class="terminal-2939949418-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-2939949418-line-17)">
+  </text><text class="terminal-2939949418-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-2939949418-line-18)">
+  </text><text class="terminal-2939949418-r1" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-2939949418-line-19)">
+  </text><text class="terminal-2939949418-r1" x="976" y="508" textLength="12.2" clip-path="url(#terminal-2939949418-line-20)">
+  </text><text class="terminal-2939949418-r1" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-2939949418-line-21)">
+  </text><text class="terminal-2939949418-r1" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-2939949418-line-22)">
   </text>
       </g>
       </g>