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):
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:
In C#, this would be represented as:
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:
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:
Using this flexible class, you may now generate our list
CSS using the following C#:
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:
Which can then be used to decorate properties and also in the CreateCss
method
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:
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:
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:
To support this, our base Css
class has a new property called Children
, which is simply a collection of other Css
blocks:
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:
Of note:
the class inherits from our base
Css
class described aboveit sets its own properties
it implements an `IClickableItem` interface
To use it in code, a developer simply has to use the Mix
function:
Because it is self-contained in a separate class, it may be mixed into any number of other properties throughout your site:
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.