Skip to content

Fixed CSS transparency bug in _style_properties.py #5890

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

edward-jazzhands
Copy link
Contributor

@edward-jazzhands edward-jazzhands commented Jun 24, 2025

Please review the following checklist.

  • [ N/A ] Docstrings on all new or modified functions / classes
  • [ N/A ] Updated documentation
  • Updated CHANGELOG.md (where appropriate)

I believe I've found the fix for this issue as originally reported in the Discord help channel.

So first off, original MRE showcasing the problem since, as requested, we're going straight to PR without an attached issue:

from textual.app import App
from textual.widgets import Switch, Static
from textual.containers import Container

class TextualApp(App[None]):

    CSS = """
    Screen { background: darkblue; align: center middle; }
    #my_container {
        width: 50%; height: 50%;
        align: center middle;
        border: solid yellow;
        background: red;
        &.-transparent { background: transparent; }        
    }
    """

    def compose(self):
        with Container(id="my_container"):
            yield Static("Make container transparent:")
            yield Switch()

    def on_switch_changed(self, event: Switch.Changed):

        my_container = self.query_one("#my_container")
        if event.value:
            my_container.styles.background = "transparent"  # before fix: this doesn't work
            # my_container.add_class("-transparent")     # adding a CSS class works fine however
        else:
            my_container.styles.background = "red"
            # my_container.remove_class("-transparent")

TextualApp().run()

The issue was that in the ColorProperties class in css/_style_properties.py, it was not accounting for the case where a named color might have alpha built into it. Which is of course only one named color, "transparency".

Line in question:

parsed_color = parsed_color.with_alpha(alpha)

In the fix, I've added an extra line:

      try:
          parsed_color = Color.parse(token)
          _r, _g, _b, alpha, _, _ = parsed_color    # new line

Previously it would only get the alpha if token.endswith("%"), which was missing the edge case where the string is "transparent". Now after parsing the string, it extracts whatever alpha value is to re-use it for the parsed_color.with_alpha(alpha) call.

I thought this was a nice solution since its a one-line addition, which is a bit more elegant than making an extra condition just for the "transparent" string. But regardless, I'm pretty sure this is the root of the issue. Let me know if you think this is maybe not the best way to fix it.

@willmcgugan
Copy link
Member

Aha, so its is making the alpha 1 regardless?

That looks like it would fix the case of transparent, but I think what we want to do is multiply the alpha. This would permit a color variable with an existing alpha, plus an additional alpha. Something like "rgba(100,20,20,0.5) 50%"

How about replacing the with_alpha with multiply_alpha?

@edward-jazzhands
Copy link
Contributor Author

edward-jazzhands commented Jun 24, 2025

Yeah that's exactly right, It was just setting it to the default alpha of 1.0 for all named colors which includes "transparent".

Nice solution with multiply_alpha, that works great. With that implemented the extra retrieval of the alpha variable was unnecessary and so I removed that line. Now the multiply_alpha method just uses the parsed color's internal alpha setting directly.

@willmcgugan
Copy link
Member

Awesome. Can I request a snapshot test?

@edward-jazzhands
Copy link
Contributor Author

Yes that would be appropriate! Sorry didn't occur to me that this is related to visual output so a snapshot would be in order. That might take me a bit, I'm not super familiar with the snapshot system.

@willmcgugan
Copy link
Member

Let me know if you need any pointers.

@edward-jazzhands
Copy link
Contributor Author

I have added a snapshot test. Marked it as a regression test linking to this PR, I believe that's what I was supposed to do.

Love the snapshot system btw, I'll be using that more often now.

@willmcgugan
Copy link
Member

Thanks

@willmcgugan willmcgugan merged commit 629ffb5 into Textualize:main Jun 26, 2025
23 checks passed
@edward-jazzhands edward-jazzhands deleted the fix_css_transparency branch July 8, 2025 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants