Razor Pages - CSS Isolation - styles for some HTML tags are not working
Asked Answered
E

5

12

I'm trying to style body, header and form tags in my ASP.NET Web App using Razor Pages, CSS Isolation. Styles created in scoped CSS file (_Layout.cshtml.css) for some HTML tags are not working. The same for other components files. Adding a class for those tags and style class selectors in scoped CSS file also doesn't work.

Code - a part of _Layout.cshtml:

    <head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>@ViewData["Title"] - RazorTest</title>
  <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
  <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
  <link rel="stylesheet" href="~/css/_Layout.cshtml.css" asp-append-version="true" />
  <link rel="stylesheet" href="~/RazorTest.styles.css" asp-append-version="true" />
</head>

<body>
  <header>
    <nav>
      <div>
        <img src="" alt="">
        <a href=""></a>
      </div>
    </nav>
  </header>
  <div class="container">
    <form action="">
      <input type="text">
    </form>
    <main role="main" class="pb-3">
      @RenderBody()
    </main>
  </div>

  <footer class="border-top footer text-muted">
    <div class="container">
      &copy; 2022 - RazorTest - <a asp-area="" asp-page="/Privacy">Privacy</a>
    </div>
  </footer>

_Layout.chstml.css:

body {
  background-color: #444;
}

header {
  border: 10px solid red;
}

form {
  border: 10px solid cyan;
}

input {
  border: 10px solid greenyellow;
}

nav {
  border: 10px solid blue;
}

div {
  border: 10px solid black;
}

main {
  border: 10px solid green;
}

img {
  width: 100px;
  height: 100px;
  border: 10px solid orange;
}

Let me show that on SS's: _Layout.cshtml and _Layout.cshtml.css files

Browser output

Everything works well when I move my CSS file to wwwroot/css directory and link it in _Layout.cshtml file. Styles for those tags also works when added to site.css file. Screenshots:

_Layout.cshtml and _Layout.cshtml.css files

Browser output

Why styles for some tags are not working when added in scoped CSS file?

Elsaelsbeth answered 24/3, 2022 at 19:3 Comment(2)
Might be styles in another stylesheet conflictingBatten
It's not the case. It's a fresh, new project, no other styles are applied for those elements.Elsaelsbeth
L
5

If you use .AddRazorRuntimeCompilation() for hot reload, try build without it. Beside the tag-helper issue mentioned above, it is a build step.

Just one thing to note, CSS isolation is a build step, so it doesn't work with Razor Runtime Compliation Beside tag-helper issue mentioned above, scoped css is build time

Faced the same issue and found this article.

Lippe answered 25/8, 2022 at 19:52 Comment(0)
I
4

I encountered similar behavior a few times when testing CSS isolation in ASP.NET 6 with Razor pages.

I noticed that not all HTML element receive a scope identifier and therefore are not affected by the scoped CSS file.

Here's a part of my final [PROJECT_NAME].styles.css file (included as link element in the page layout):

form[b-l6oslukat8] {
    background-color: orange;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
}

And here is related part of the final HTML file where the identifier (b-l6oslukat8) should be but isn't:

<section b-l6oslukat8="" class="full page">
    <form data-form-type="login">
        <input b-l6oslukat8 type="text" id="Username" name="Username">
        <input b-l6oslukat8 type="password" id="Password" name="Password">
    </form>
</section>

Looks like this is a case with your final HTML/CSS as well. It seems to me it's a bug in the implementation of CSS isolation in .NET 6.

Impracticable answered 29/3, 2022 at 12:40 Comment(6)
So is the consensus to stay away from CSS Isolation for the time being?Ileus
Personally I switched to general CSS in wwwroot and more specific styles inside the <style> tag in Razor page code. I have no idea why some tags are being omitted the identifiers. I found out that any time I tried using asp-* tag helpers, CSS Isolation was not working as well. For me it's right now too much of a hassle to search for workarounds for this rather small issue.Impracticable
Dotnet team is working on it: github.com/dotnet/aspnetcore/issues/30213Impracticable
@STETT, that GitHub issue (30213) is not relevant to the issue being reported here.Patriliny
i can also confirm that css isolation doesn't work w/ html tags using asp-* tag helpers. this is a considerable bug. I will not use css isolation due to this issue.Deepsix
@Patriliny - The team working on the issue posted 30213 as related. "CSS isolation only applies to HTML tags, the moment you use a tag helper (like form, asp-for, etc), those don't apply any longer." github.com/dotnet/aspnetcore/issues/40996Hogtie
P
1

I just encountered this issue, twice, on my first attempt to use CSS isolation (a.k.a. scoped CSS) in Razor Pages. This issue affects my header element and an img element. I found this issue on GitHub:

https://github.com/dotnet/aspnetcore/issues/41507#issuecomment-1117287553

What's happening there is that a tag helper is acting over the img tag and that results in the tag not being treated as an HTML tag. CSS isolation only applies to HTML tags, so that's why it's not being applied in this case (since it's not just a tag).

CSS isolation only applies to HTML tags within the document, otherwise it would potentially break the isolation boundary of other tags or components.

We do have an issue opened on making possible for other components and tag helpers to opt-in into receiving the CSS scope from a call/use point, which would result in what you are looking for. I would suggest you upvote this issue instead dotnet/razor#7606

As a workaround, we would suggest you wrap the tag inside another element like a div, and update your CSS rule to account for it.

Note the proposed workaround in the last paragraph. I find the explanation to be unacceptable, because this affects a header element, which has no tag helper in Razor Pages.

https://www.learnrazorpages.com/razor-pages/tag-helpers/

[Edit] I reported this issue. https://github.com/dotnet/aspnetcore/issues/48225

Patriliny answered 12/5, 2023 at 23:40 Comment(1)
Working on a fix: github.com/dotnet/razor/pull/9046Washable
M
0

Why styles for some tags are not working when added in scoped CSS file?

Maybe iy is not enough tou take precedence.

You can try to use either specificity or the natural cascade to override the styling,so that it may be enough to take precedence.For example,you can change:

img {
  width: 100px;
  height: 100px;
  border: 10px solid orange;
}

to

body > div > img  {
    width: 100px;
      height: 100px;
      border: 10px solid orange;
}

And if you want to change the style which cannot use either specificity or the natural cascade,you can try to add the style into the view,for example:

<style>
  body {
    background-color: #444;
  }

</style>
Milburr answered 25/3, 2022 at 2:39 Comment(1)
I tried it before, didn't help.Elsaelsbeth
M
0

I implemented a crude-but-effective solution to this a while back, and I was just reusing it, which prompted me to share it.

So, the real problem is that .NET alters the scoped CSS, adding the scope-identifier attribute (a "b-" attribute with an empty value, such as b-phmxwtvfx5) to all of the the CSS rules. This effectively disassociates the rules from the elements that .NET does not add that scope-identifier attribute to in the rendered Razor HTML.

This is true for tag helpers and the other missed elements (header, img, etc.). My solution is to add it myself, client-side.

$(document).ready(function() {
  var scopedID;
  const el = document.querySelector('#se');

  for (const attr of el.attributes) {
    if (attr.name.indexOf('b-') == 0) {
      console.log(attr + ": bingo!");
      scopedID = attr.name;
      break;
    }
  }

  var tagHelperInputs = document.querySelectorAll("input:not([" + scopedID + "] [readonly])");

  for (const inputEl of tagHelperInputs) {
    inputEl.setAttribute(scopedID, "");
  }

  var tagHelperLabels = document.querySelectorAll("label:not([" + scopedID + "])");

  for (const labelEl of tagHelperLabels) {
    labelEl.setAttribute(scopedID, "");
  }
});
.form-control.sa {
  max-width: 40ch;
}

label {
  font-weight: bold;
}

.form-grid-row {
  display: grid;
  grid-template-columns: 11ch auto;
  margin-bottom: 15px;
}
@page @model ParticipantPortalIdentity.Areas.KeystoneLogin.Pages.Account.AnswerSecurityQuestionsModel

<h1 id="se" class="h2">Security Questions</h1>
<h2 class="h3 mb-4">
  Please answer following security questions:
</h2>
<form asp-page-handler="CheckQAs">
  <div class="mb-3">
    <div class="form-grid-row">
      <label asp-for="SecurityQuestion1" class="form-label">Question </label><span class="">@Model.SecurityQuestion1</span>
      <label asp-for="SecurityAnswer1">Answer <span class="required-field-indicator fs-5">*</span></label>
      <input asp-for="SecurityAnswer1" size="25" class="form-control sa" autocomplete="off" autocapitalize="off" spellcheck="false">
    </div>
    <span asp-validation-for="SecurityAnswer1" class="alert alert-danger" role="alert"></span>
  </div>
  <div class="mb-3">
    <div class="form-grid-row">
      <label asp-for="SecurityQuestion2" class="form-label">Question </label><span>@Model.SecurityQuestion2</span>
      <label asp-for="SecurityAnswer2">Answer <span class="required-field-indicator fs-5">*</span></label>
      <input asp-for="SecurityAnswer2" size="25" class="form-control sa" autocomplete="off" autocapitalize="off" spellcheck="false">
    </div>
    <span asp-validation-for="SecurityAnswer2" class="alert alert-danger" role="alert"></span>
  </div>
  <div>
    <button type="submit" class="btn btn-fp-primary">Submit</button>&nbsp;<a href="~/" class="btn btn-primary">Cancel</a>
  </div>

I put an id of "se" (scoped-ID element) to query the element's attributes client-side, find the scope identifier, which starts with "b-" (unless you change it your project), then add that to the elements, by element type, that I need it added to.

Mastoidectomy answered 22/5, 2024 at 21:29 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.