dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.49k stars 10.04k forks source link

[Blazor] ::deep does not work in combination with [dir="rtl"] #45138

Closed vnbaaij closed 1 year ago

vnbaaij commented 2 years ago

Is there an existing issue for this?

Describe the bug

If you have an isolated CSS file that contains [dir="rtl"]-selector in combination with ::deep-selector the generated CSS does not work correctly because there is no space between the two selectors.

Because of the space not being there, targeting rtl-languages with isolated CSS icw [dir] selector is very hard/impossible.

Expected Behavior

The generated CSS should contain a space between [dir="rtl"]-selector and ::deep-selector.

What gets generated:

[dir="rtl"][b-fl]  fluent-button {
    display: none;
    position: fixed;
    bottom: 45px;
    left: 20px;
    right: unset;
    z-index: 99;
    cursor: pointer;
}

What should be generated:

[dir="rtl"] [b-fl]  fluent-button {
    display: none;
    position: fixed;
    bottom: 45px;
    left: 20px;
    right: unset;
    z-index: 99;
    cursor: pointer;
}

NOTE: There are 2 spaces generated between the generated ::deep selector and the fluent-button selector

Steps To Reproduce

Repo: https://github.com/vnbaaij/CssIsolationBug

Standard new Blazor WebAssembly project.

No red text/border Going to Dev Tools you'll find in CssIsolationBug.styles.css:

:
/* /Shared/SurveyPrompt.razor.rz.scp.css */
[dir="rtl"][b-e23gho3fj3]  .rtlspecific {
    color: red;
    border: 1px dotted red;
}

Adding the space between [dir="rtl"] and [b-e23...] in Dev Tools gives the desired effect:

image

Exceptions (if any)

No response

.NET Version

.NET 6 and higher

Anything else?

No response

Nick-Stanton commented 1 year ago

It seems that leading with a square-bracketed attribute selector (i.e. [dir="rtl"] ::deep .rtlspecific) is not currently supported for Razor's ::deep pseudo-element. In a designed use case (e.g. ::deep h1), the expected behavior is for the output to have no space.

CC @SteveSandersonMS on whether this scenario is intended behavior.

Repro: https://github.com/Nick-Stanton/CSSMissingSpace

SteveSandersonMS commented 1 year ago

@Nick-Stanton I'll look into the more general point you've raised. Thanks!

@vnbaaij It's possible I'm misunderstanding your objective, but it looks as if you're just not using ::deep correctly. Your code looks like this:

[dir="rtl"] ::deep .rtlspecific

... and what that means is "match anything in this component that has [dir="rtl"] and find any descendant (in any component) with .rtlspecific".

But that's not really what you want, is it? Don't you want to put dir="rtl" on the html or body element or similar? You're not actually putting dir=rtl onto something in the current component, are you?

I think what you really mean is "when an ancestor has [dir=rtl], match any element from this component or any descendant with .rtlspecific". So I think the syntax you should use is this:

[dir="rtl"] * ::deep .rtlspecific

Doesn't that work?

BTW https://github.com/vnbaaij/CssIsolationBug gives a 404. Maybe it's a private repo.

ghost commented 1 year ago

Hi @vnbaaij. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

vnbaaij commented 1 year ago

Oops, repo is private indeed. Will correct that first later (today probably).

But that's not really what you want, is it? Don't you want to put dir="rtl" on the html or body element or similar? You're not actually putting dir=rtl onto something in the current component, are you?

No, I'm not doing that. What I'm doing is indeed setting dir="rtl" on a higher level (through a user selected switch). I then want to target (part of) my component with some specific rtl styling.

I think what you really mean is "when an ancestor has [dir=rtl], match any element from this component or any descendant with .rtlspecific". So I think the syntax you should use is this:

Yes, that is what I want

`[dir="rtl"] * ::deep .rtlspecific

I'll give this a try and report back. Thanks!

SteveSandersonMS commented 1 year ago

BTW if .rtlspecific is within the current component (not a descendant) then you wouldn't even need ::deep at all. The syntax would just be:

[dir=rtl] .rtlspecific { ... }

That matches things in the current component with .rtlspecific as long as some ancestor has [dir=rtl].

vnbaaij commented 1 year ago

BTW if .rtlspecific is within the current component (not a descendant) then you wouldn't even need ::deep at all. The syntax would just be:

Yes, understood. Thing is I'm 'composing' a lot of things with components getting nested and therefore need the ::deep. For example, I have a TableOfContents component that has a <ul> list in an Accordion component and I need to target the <ul> from the TableOfContents CSS.

I've made the repo public now.

The [dir="rtl"] * ::deep .rtlspecific syntax works, so there is a way to get it working now.

However, I do still think it is strange I would need to do it like this when compared to the 'normal' LTR version. In the repo site I now have the CSS like this (I know I do not really need the ::deep in this case, but it illustrates the effect):

::deep .rtlspecific {
    color: green;
    border: 1px dotted green;
}
[dir="rtl"] * ::deep .rtlspecific {
    color: red;
    border: 1px dotted red;
}

Feels strange to have this difference, right?

SteveSandersonMS commented 1 year ago

Feels strange to have this difference, right?

The difference is only because ::deep .rtlspecific { ... } is shorthand for * ::deep .rtlspecific { ... }. If you wish, you could use the longhand version for the ltr case and then the code would look more symmetrical.

I'll close this as answered now. Hope that's OK.