Blackball Software

View Original

True Object Oriented CSS using C#

One of the reasons Foundation is such an affordable way to build bespoke software is our ability to abstract common logic into our libraries while still being able to 100% customize for each client as required. For our “under the hood” stuff, like data access and caching, we can use standard object-oriented mechanisms like interfaces & inheritance. Unfortunately for front-end work, very little has been contributed in terms of standards and best practice.

Front-end websites typically consist of three completely distinct, and yet completely interdependent languages - HTML, CSS & Javascript. This means additional languages for our developers to learn, and additional cost and inefficiency as we try to maintain different libraries and upgrades across projects.

In this article, I will share how Blackball has created an object-oriented framework for one of these components - CSS. By using C# to describe our CSS, we open up the full power of object-oriented programming, as well as a few extra bonus features.

TL;DR;

By the end of this article, your C# developers will be able to write CSS like this (full source code at end of article):

See this content in the original post

Why OO CSS?

  • Compile-time checking

  • No external dependencies like gulp or webpack - just your regular C# compiler

  • Options to later generate different CSS based on browser types, screen size etc

  • Familiar environment and constructs for back-end developers

  • Ability to share and update styles between projects, while allowing them to remain 100% flexible

Features

Let’s get into the code. I’ve stripped things back to the basics here and will try to take you through progressively, adding more and more features.

The base class

First, we have to consider exactly what a base class is in CSS. It has to be self contained, it will probably have one or more properties. Here is the most basic example:

See this content in the original post

In C#, this would be represented as:

See this content in the original post

This is fine but it’s not re-usable. Consider another block of CSS that also included a height property. We don’t want our developers having to create a C# class for every single block of CSS - there would be thousands, and it would be very slow. Instead, let me introduce our base class which I have simply called Css. This class simply has every single Css property available, all initially set to null. When we come to render, we simply cherry-pick the non-null values:

See this content in the original post

At first it seems burdensome to have every CSS class listed, but in actual fact it isn’t. Remember also that the C# compiler strips out unused values so there is no performance overhead.

Note also my inclusion of the two top properties - SelectorName and Selectortype. Combined with a little bit of good old fashioned reflection, these classes may now render themselves like so:

See this content in the original post

Using this flexible class, you may now generate our list CSS using the following C#:

See this content in the original post

Property names

You may have noticed that the property names of my class (e.g. BackgroundColor) do not confirm to the exact semantics of CSS (i.e. background-color).. To address this, I have a simple attribute which I can apply to rogue class names:

See this content in the original post

Which can then be used to decorate properties and also in the CreateCss method

See this content in the original post

Property types

Another peculiarity about CSS is that each property can have a variety of different types. Consider the width property for example, in CSS all of these are valid:

See this content in the original post

Some of these are int or double values, but are in different units such as px or em. There are various keywords such as auto or inherit which from C#’s point of view can only be type string. You can even have calculations and of course every property may have the !important suffix.

To address these, and more, are architecture has the CssProperty<T> class:

See this content in the original post

Using this, I can now set the Width property of my base Css class to type CssProperty<double>, and in code set it as list.Width.Pixels().Value = 400

Note also the fluent interface which lets me chain commands together and makes it overall a little easier to read.

Calculations

The CssProperty class also facilitates another powerful feature - calculations. Specifically, because my properties like width, height etc are doubles, I can add them together. This becomes very powerful later when we introduce variables.

Nested classes

All of the complexity above is required simply to allow you to render top-level CSS blocks. However, most CSS is actually targeting classes within classes, such as:

See this content in the original post

To support this, our base Css class has a new property called Children, which is simply a collection of other Css blocks:

See this content in the original post

Variations of the same technique can be used to render pseudo elements (e.g. :before), media queries, and also concepts of mixins or extends that are offered by existing CSS preprocessors such as LESS or SCSS respectively.

Sharing CSS between projects

I said earlier that it was inefficient to create a new class for every style - hence the flexibility of the base Css class above. However sometimes it is advantageous to separate a collection of styles out. Consider this class, which describes how a “clickable” item should look:

See this content in the original post

Of note:

  • the class inherits from our base Css class described above

  • it sets its own properties

  • it implements an `IClickableItem` interface

To use it in code, a developer simply has to use the Mix function:

See this content in the original post

Because it is self-contained in a separate class, it may be mixed into any number of other properties throughout your site:

See this content in the original post

The cool part

Note in particular that the various code blocks are not referring to the ClickableItem class directly - they are all routing through its IClickableItem interface. This means that on any project, all you need to do is inject a new implementation via your IoC container and voila - all the code on your entire site is updated.

At Blackball, we include this interface and the default implementation in our base Foundation Nuget package, then override as required for specific projects.

The IClickableItem is a trivial example - we have interfaces for tables, headings, loading feedback etc etc. It is extremely powerful and extremely flexible.

To conclude

There are plenty of ways to skin a cat. We are well aware of the various preprocessors, webpack plugins etc etc that are available to wrangle and re-use CSS. However we discarded these because it meant other dependencies in our code, and other skillsets to learn.

This does not mean however that our mechanism is any faster to develop on, or that the resulting CSS is any better. It just gives us a huge advantage when it comes to maintainability and re-usability across different projects.

The source code

Unfortunately it’s not practical for me to pull this code into a separate repo for you to download. However below I have cobbled together the key methods. It won’t compile, but it should be easy enough to work out if you are a C# developer. Have fun.

See this content in the original post