diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33d6859dc5..ce2a9fd72b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added `index` to `ListView.Selected` event https://github.com/Textualize/textual/pull/5973
- Added `layout` switch to Static.update https://github.com/Textualize/textual/pull/5973
+### Fixed
+
+- Fixed `TextArea` issue with the `css` theme, where the background color was stuck from the previous theme https://github.com/Textualize/textual/issues/5964
+
### Changed
- Improved rendering of Markdown tables (replace Rich table with grid) which allows text selection https://github.com/Textualize/textual/pull/5962
diff --git a/src/textual/widgets/_text_area.py b/src/textual/widgets/_text_area.py
index 6e430fb5ec..366d32ddde 100644
--- a/src/textual/widgets/_text_area.py
+++ b/src/textual/widgets/_text_area.py
@@ -860,6 +860,14 @@ def _set_theme(self, theme: str) -> None:
self.styles.color = Color.from_rich_color(color)
if background:
self.styles.background = Color.from_rich_color(background)
+ else:
+ # When the theme doesn't define a base style (e.g. the `css` theme),
+ # the TextArea background/color should fallback to its CSS colors.
+ #
+ # Since these styles may have already been changed by another theme,
+ # we need to reset the background/color styles to the default values.
+ self.styles.color = None
+ self.styles.background = None
@property
def available_themes(self) -> set[str]:
diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_css_theme_updates_background.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_css_theme_updates_background.svg
new file mode 100644
index 0000000000..cc32704154
--- /dev/null
+++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_css_theme_updates_background.svg
@@ -0,0 +1,153 @@
+
diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_read_only_cursor_rendering.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_read_only_cursor_rendering.svg
index b1c1b9b98a..86db6b1030 100644
--- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_read_only_cursor_rendering.svg
+++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_read_only_cursor_rendering.svg
@@ -19,59 +19,59 @@
font-weight: 700;
}
- .terminal-2506374631-matrix {
+ .terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-2506374631-title {
+ .terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-2506374631-r1 { fill: #121212 }
-.terminal-2506374631-r2 { fill: #0178d4 }
-.terminal-2506374631-r3 { fill: #c5c8c6 }
-.terminal-2506374631-r4 { fill: #999997;font-weight: bold }
-.terminal-2506374631-r5 { fill: #f8f8f2 }
+ .terminal-r1 { fill: #121212 }
+.terminal-r2 { fill: #0178d4 }
+.terminal-r3 { fill: #c5c8c6 }
+.terminal-r4 { fill: #959595;font-weight: bold }
+.terminal-r5 { fill: #e0e0e0 }
-
+
-
+
-
+
-
+
-
+
- TextAreaSnapshot
+ TextAreaSnapshot
-
-
-
- ▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-▊1 Hello, world! ▎
-▊▎
-▊▎
-▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
+
+
+
+ ▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
+▊1 Hello, world! ▎
+▊▎
+▊▎
+▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_themes[css].svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_themes[css].svg
index 0d6b98a198..9e850d91d4 100644
--- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_themes[css].svg
+++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_text_area_themes[css].svg
@@ -19,84 +19,84 @@
font-weight: 700;
}
- .terminal-1378439235-matrix {
+ .terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-1378439235-title {
+ .terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-1378439235-r1 { fill: #121212 }
-.terminal-1378439235-r2 { fill: #0178d4 }
-.terminal-1378439235-r3 { fill: #c5c8c6 }
-.terminal-1378439235-r4 { fill: #71716e }
-.terminal-1378439235-r5 { fill: #569cd6 }
-.terminal-1378439235-r6 { fill: #f8f8f2 }
-.terminal-1378439235-r7 { fill: #dcdcaa }
-.terminal-1378439235-r8 { fill: #cccccc }
-.terminal-1378439235-r9 { fill: #9cdcfe }
-.terminal-1378439235-r10 { fill: #999997;font-weight: bold }
-.terminal-1378439235-r11 { fill: #b5cea8 }
-.terminal-1378439235-r12 { fill: #7daf9c }
-.terminal-1378439235-r13 { fill: #4ec9b0 }
-.terminal-1378439235-r14 { fill: #ce9178 }
+ .terminal-r1 { fill: #121212 }
+.terminal-r2 { fill: #0178d4 }
+.terminal-r3 { fill: #c5c8c6 }
+.terminal-r4 { fill: #6b6b6b }
+.terminal-r5 { fill: #569cd6 }
+.terminal-r6 { fill: #e0e0e0 }
+.terminal-r7 { fill: #dcdcaa }
+.terminal-r8 { fill: #cccccc }
+.terminal-r9 { fill: #9cdcfe }
+.terminal-r10 { fill: #959595;font-weight: bold }
+.terminal-r11 { fill: #b5cea8 }
+.terminal-r12 { fill: #7daf9c }
+.terminal-r13 { fill: #4ec9b0 }
+.terminal-r14 { fill: #ce9178 }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- TextAreaSnapshot
+ TextAreaSnapshot
-
-
-
- ▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
-▊1 defhello(name):▎
-▊2 x=123▎
-▊3 whilenotFalse:▎
-▊4 print("hello "+name)▎
-▊5 continue▎
-▊6 ▎
-▊▎
-▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
+
+
+
+ ▊▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎
+▊1 defhello(name):▎
+▊2 x=123▎
+▊3 whilenotFalse:▎
+▊4 print("hello "+name)▎
+▊5 continue▎
+▊6 ▎
+▊▎
+▊▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎
diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py
index 4ffcec995d..6bde2bdd17 100644
--- a/tests/snapshot_tests/test_snapshots.py
+++ b/tests/snapshot_tests/test_snapshots.py
@@ -4421,3 +4421,33 @@ async def on_mount(self) -> None:
await asyncio.sleep(0.01)
assert snap_compare(MDApp(), press=["1", "wait:500"])
+
+
+def test_text_area_css_theme_updates_background(snap_compare):
+ """Regression test for https://github.com/Textualize/textual/issues/5964"""
+
+ class TextAreaThemeApp(App):
+ def compose(self) -> ComposeResult:
+ text_area_control = TextArea(
+ "This TextArea theme is always `css`.",
+ theme="css",
+ id="text-area-control",
+ )
+ text_area_control.cursor_blink = False
+
+ text_area_variable = TextArea(
+ "This TextArea theme changes from `github_light` to `css`.\n"
+ "The colors should match the TextArea above.",
+ theme="github_light",
+ id="text-area-variable",
+ )
+ text_area_variable.cursor_blink = False
+
+ yield text_area_control
+ yield text_area_variable
+
+ def on_mount(self) -> None:
+ text_area = self.query_one("#text-area-variable", TextArea)
+ text_area.theme = "css"
+
+ assert snap_compare(TextAreaThemeApp())