textual
textual copied to clipboard
Opacity/transparency issues with overlapped widgets
This change [to how opacity works] might have inadvertently introduced a bug for layers with opacity. Here's a simple example adapted from the docs for Layers, with a binding that changes the opacity of #box1.
Before v0.29.0
After v0.29.0
Excerpt of a comment posted by @TomJGooding in https://github.com/Textualize/textual/issues/3652#issuecomment-1802888662
The examples below show situations in which widget overlaps don't take transparencies into account correctly.
Base app:
from textual.app import App
from textual.widgets import Label
class BGApp(App):
CSS_PATH = "bg.tcss"
def compose(self):
yield Label("below", id="below")
yield Label("above", id="above")
if __name__ == "__main__":
BGApp().run()
- Overlapping widgets because of layers and the top one has a transparent background:
Screen {
layers: below above;
}
#below {
width: 30;
height: 5;
layer: below;
background: blue;
}
#above {
width: 20;
height: 3;
layer: above;
background: red 0%;
}
- Overlapping widgets because of layers and
opacity: 0%set on the top one:
Screen {
layers: below above;
}
#below {
layer: below;
width: 30;
height: 5;
background: blue;
}
#above {
layer: above;
width: 20;
height: 3;
background: red;
opacity: 0%;
# background: red 0%;
}
- Overlapping widgets because of offsets and the top one has
opacity: 0%:
#below {
width: 30;
height: 5;
background: blue;
}
#above {
offset: 0 -3;
width: 20;
height: 3;
background: red;
opacity: 0%;
}
- Overlapping widgets because of offsets and top one has transparent background:
#below {
width: 30;
height: 5;
background: blue;
}
#above {
offset: 0 -3;
width: 20;
height: 3;
background: red 0%;
}
Thanks @rodrigogiraoserrao for checking all these scenarios.
After looking at this again , it seems only the opacity style worked before v0.29, whereas the background percentage has possibly never been taken into account.
This probably isn't helpful given the significant changes in #2814, but making a note just in case.
EDIT: Digging deeper, actually only opacity: 0% worked before v0.29. For example background: white; opacity: 50%; would show as grey, rather than a light blue as you might expect.
Confirmed this is still broken on main as of 17th July 2024 (commit hash: 0d256073740264bf).
MRE without external CSS file:
from textual.app import App
from textual.widgets import Label
class BGApp(App):
CSS = """\
Screen {
layers: below above;
}
#below {
width: 30;
height: 5;
layer: below;
background: blue;
}
#above {
width: 20;
height: 3;
layer: above;
background: red 0%;
}
"""
def compose(self):
yield Label("below", id="below")
yield Label("above", id="above")
if __name__ == "__main__":
BGApp().run()