CshtmlComponent - Scoped CSS
Tags: aspnetcore, dotnet, csharp, webdev
Published: 2020-10-18 12:14:10

[CshtmlComponent](https://cshtml-component.acmion.com) 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](https://cshtml-component.acmion.com/#usage).
+ Install [SCSS](https://sass-lang.com/install).
+ 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>
```
+ 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;
        }
    }
}
```
+ 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>
```
+ Run SCSS from the commandline with this command
```
sass --watch Components:wwwroot/dist/Components --style compressed
```
+ 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](https://github.com/Acmion/CshtmlComponentScopedCss) for an example on scoped CSS in CshtmlComponent.