loading...

CshtmlComponent - Scoped CSS

acmion profile image Acmion ・2 min read

CshtmlComponent is a component library for ASP.NET Core MVC or Razor Pages applications. The library has an extensive feature set and has served myself well.

Scoped CSS

Almost all of the major web component libraries or frameworks support scoped CSS. Scoped CSS is a feature that once you get used to it, you never want to go back to writing global CSS. CshtmlComponent does not explicitly take a stance on the issue, but still allows one to write scoped CSS, albeit SCSS (or SASS) has to be used. This blog post describes how this can be achieved.

Scoped CSS with CshtmlComponent

  • Install and configure CshtmlComponent. See instructions from the official documentation.
  • Install SCSS.
  • Create the component "ExampleComponent", in other words, create the files /Components/ExampleComponent.cshtml and /Components/ExampleComponent.cshtml.cs. The files paths are relative to the ASP.NET Core application root path. See more instructions in the documentation.
  • In /Components/ExampleComponent.cshtml create markup that resembles this:
<div class="example-component">
    <div class="example-component-content">
        <!-- Content here. -->
    </div>

    <div class="example-component-slot-content">
        <!-- Content here. -->

        <!-- NOTE: Important class="child-content". -->
        <div class="child-content">
            <!-- Render the slot content here. See documentation. -->
        </div>
    </div>

    <!-- NOTE: Important class="child-content". -->
    <div class="example-component-child-content child-content">
        <!-- Render the child content here. See documentation. -->
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode
  • Create the file /Components/ExampleComponent.cshtml.scss with content that resembles this:
.example-component
{
    // Style the wrapper here.
    padding: 10px;
    background: rgba(255, 0, 0, 0.1);

    & > .example-component-slot-content
    {
        // Apply styles to the slot content container here.
        padding: 6px;
        border: 4px solid rgba(0, 0, 0, 0.4);
    }

    & > *:not(.child-content)
    {
        // Apply styles to child tags that are used by the component (but not nested under .child-content) here.
        // Note: Requires a wrapper element. In this component, the elements with class="example-component-content" and class="example-component-slot-content" are the wrapper elements. Styles are only applied to children of the wrapper elements.
        h2
        {
            color: red;
        }

        .date
        {
            font-style: italic;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
  • The SCSS under & > *:not(.child-content) is now scoped!
  • Add this to code to ExampleComponent.cshtml
<CshtmlHead>
    <link rel="stylesheet" href="~/dist/Components/ExampleComponent.cshtml.css" />
</CshtmlHead>
Enter fullscreen mode Exit fullscreen mode
  • Run SCSS from the commandline with this command
sass --watch Components:wwwroot/dist/Components --style compressed
Enter fullscreen mode Exit fullscreen mode
  • Enjoy scoped CSS in CshtmlComponent!

Notes

The SCSS based scoped CSS in CshtmlComponent is not a 100% substitution for how the scoped CSS works in other frameworks. For example, the class names do not get mangled.

Additionally, this SCSS based scoping demands that wrapper tags are added to the components. In other words, if a tag was added directly under the main class (in this case "example-component"), then styling under & > *:not(.child-content) would not be applied to it.

Regardless, scoped CSS is possible in CshtmlComponent and works just fine.

See this GitHub repository for an example on scoped CSS in CshtmlComponent.

Discussion

pic
Editor guide