A Style and Css builder for Blazor and ASP.NET Core web applications inspired by the classnames javascript library.
The main classes of the package injected through Microsoft.Extensions.DependencyInjection so you first have to register it:
public void ConfigureServices(IServiceCollection services) {
services.AddCssBuilder();
services.AddStyleBuilder();
In case of the CssBuilder you can add options also:
public void ConfigureServices(IServiceCollection services) {
services.AddCssBuilder(options => {
options.PropertyToClassNameConverter =
CssBuilderNamingConventions.KebabCaseWithUnderscoreToHyphen;
options.EnumToClassNameConverter =
CssBuilderNamingConventions.KebabCaseWithUnderscoreToHyphen;
options.ExcludeDuplication = false;
});
Then you need to inject into the .cshtml or .razor page.
@inject ICssBuilder Css
@inject IStyleBuilder Styles
And use it:
<div class="@Css["foo", new { Bar = false, Baz = true}]"
style="@Styles[("width", "100px"), new { Height = "200px" }]">...</div>
Output:
<div class="foo baz" style="width:100px;height:200px">...</div>
When you use the CssBuilder or StyleBuilder with objects or enum values then the property name and enum value is converted to class name. It is determined at startup in configuration. The default is kebab-case with converting underscore to hyphen for bot properties and enums but it is configurable invidually. Examples:
- BarBaz -> bar-baz
- Bar_baz -> bar-baz
- Bar_Baz -> bar--baz
The CssBuilder works mainly through its indexer and it accepts several type of parameters.
Css["foo", "bar", "baz"] // -> "foo bar baz"
The first parameter is emitted if the second is true.
Css[("foo", true), ("bar", false), ("baz", true)] // -> "foo baz"
Can be used with prepared list or with iterator methods.
var cssList = new List<string>{ "foo", "bar", "baz" };
Css[cssList] // -> "foo bar baz"
var other = Css["bar", "baz"];
Css["foo", other] // -> "foo bar baz"
Can be used with enum values. The name generation is determined by options.EnumToClassNameConverter
. Default is kebab-case with converting underscore to hyphen.
public enum Values {
Foo,
Bar,
Baz
}
Css[Values.Foo, Values.Bar, Values.Baz] // -> "foo bar baz"
Can be used with generic object (Mainly with anonymous) where all the properties needs to be bool property. The name generation is determined by options.PropertyToClassNameConverter
. Default is kebab-case with converting underscore to hyphen.
Css[new { Foo = true, Bar = false, Baz = true }] // -> "foo baz"
In Blazor you can capture unmatched values in a Dictionary<string, object>
. the CssBuilder can extract the value of the "class" key and add to the class list.
Parent .razor file:
<RazorComponent class="bar baz">...</RazorComponent>
RazorComponent.razor
<div class="@Css["foo", Attributes]">...</div>
@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> Attributes { get; set; }
}
Output:
<div class="foo bar baz">...</div>
You can also start with an empty CssClassList and build it with different way with the Create method. This method also can have an options also in which case uses that to determine how the output generated. If you use multiple setups then strongly recommended to make a singleton instance from these options since it is connected to the caching mechanism. See later
var css = Css.Create();
css.Add("foo").Add("baz").AddMultiple("foo2", "baz2");
// -> "foo baz foo2 baz2"
The StyleBuilder works mainly through its indexer and it accepts several type of parameters. The parameters somme form of property value pair and an optional condition. If the value is null or empty then the property is skipped.
It can have property, value pair only or with condition. the value and condition can be a parameterless function also.
Styles[("width", "100px"), ("height", "200px", true), ("border", null)]
// -> "width:100px;height:200px"
In Blazor you can capture unmatched values in a Dictionary<string, object>
. the StyleBuilder can extract the value of the "style" key and add to the class list. the style value must be a valid style declaration block since it is processed.
Parent .razor file:
<RazorComponent style="height: 200px">...</RazorComponent>
RazorComponent.razor
<div class="@Styles[("width", "100px"), Attributes]">...</div>
@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> Attributes { get; set; }
}
Output:
<div style="width:100px;height:200px">...</div>
The property name is used as property. It is converted with kebab-case and underscore to hyphen conversion. the value can be string or the ToString method should return with the value.
Styles[new { Width = "100px", Height: "200px", Border = null }] // -> "width:100px;height:200px"
You can also start with an empty StyleDeclarationBlock and build it with different way with the Create method.
var styles = Styles.Create();
css.Add("width", "100px").Add("height", "200px").AddMultiple(("border", "1px"));
// -> "width:100px;height:200px;border:1px"
There are several process consuming operations so I made a caching mechanism for enum to class and property name to class conversion and also for object processing. This cache is connected to the options since if different options is used it is excepted to work correctly also.
Thanks for .net development team because of the documentation comments in the .net ecosystem. It helped me out to write my own documentation that hopefully have sense.
I also say thank you for my colleague Horia who designed the foxy icon.
Lastly thanks for Jed Watson for the amazing classnames javascript library.