Your Project’s CSS: Avoiding FAIL
So often projects suffer from a lack of CSS planning and forethought. Styling is often written in an ad-hoc need-to-have basis concurrently as each component or chunk of the UI is developed. Overall design is often left to the defaults that come with whichever framework was chosen. The look and feel or design implementation is often thought of as low priority and left to the rushed end bit of a sprint. Responsibility is often unassigned while multiple team members write their own CSS into the growing codebase.
The consequences of this unplanned and disorganized approach eventually start to plague the project, as CSS architecture (or lack thereof) degrades into a messy, unmaintainable, difficult to scale and increasingly slow codebase.
So let’s look at some high level considerations and strategies to avoid this:
A bit about CSS
CSS sits at an intersection between visual designers, back-end developers, and content creators. A key component of front-end development, the complexity of CSS development is often underestimated. From the point of view of back-end developers who focus on the functionality and business logic of the application, CSS may seem like a somewhat simple non-procedural markup language used to tack on design at the end of the sprint.
The reality is that CSS is easy to learn but difficult to master. The development life-cycle of your application would suffer if the front-end code wasn’t architected in a performant, scalable and maintainable fashion, and CSS is an integral if not the most important structure in this architecture.
I’ve seen many projects where the front end code fails to scale. As the product ages or as the team grows, the CSS in particular can grow into an unruly bloated and unplanned mess. CSS’s declarative and globally scoped nature tends to promote an environment where developers are hesitant to reuse or refactor code. Instead they end up appending new code which leads to multiple problems including specificity creep, poor scalability, maintainability, performance loss.. eventually leading to the inevitable and expensive rewrite.
So how can we implement CSS properly and robustly into our project, and our team?
Who should CSS?
First we should look at who should be writing and maintaining the CSS codebase. Aside from choosing the most knowledgeable CSS developer available, there are other factors that usually affect this decision, such as the size of the team, size of the project, budget, availability of developers with CSS experience, etc.
As a result, these are the oft-chosen candidates:
The developers who write the back end code
In my experience this the least desirable scenario. Most of the time back-end developers only know enough CSS to be dangerous. Since the CSS syntax is simple and quick to learn, it is easy to think you know enough to handle the application of design to whatever component your code is building. However a back-end developer’s priority is to specialize in the said back end, which is a different head space to applying design. Even if they are experienced in the planning and development of front-end architecture including CSS, they are still less likely to want to constantly switch head spaces and give it the equal priority it requires.
A ‘full stack’ developer
Maybe your team is small or there is a single mythical ‘full stack developer’ handling the entire front and back end architecture. Perhaps you are leaning on a CSS framework and/or a template to provide most of the design implementation.
These days the development stack is too large, too complex, and expanding too quickly to justify the job title ‘full stack developer’. Nobody can be an expert in all of it, a team needs to compose itself with specialists in pertinent areas of the stack. This is as true for the CSS layer as it is for the design or server management layers. Any serious development strategy needs at least one front-end developer who can architect CSS. This may or may not be your full stack developer.
A visual designer
Many visual designers have expanded their skill set into front-end development, and would make a good candidate — as long as they have strong CSS authoring and implementation experience. The two skillsets are aligned headspace wise, and the best person to make sure the design is implemented properly is the actual designer. This combined skillset however is not usually easily found.
A front-end or UI developer / architect
An experienced front-end / UI developer/architect is the best choice. This is someone who excels at:
- architecting CSS from a design perspective — is able see and dissect the design into repeatable objects and create modular code to match
- interpreting the design to know when to be pixel perfect, and when not
- working with designers and product managers to communicate limitations when it comes to implementing design and behaviour
- working with developers in shared templates, knowing how to apply hooks and refactor HTML without breaking existing developer code
- creating usable API and documentation benefiting everyone else in the team
- keeping up to date on front-end technologies, able to implement with graceful degradation and progressive enhancement, understanding browser inconsistencies
- being able to architect performant, scalable and maintainable CSS code
Do we need a CSS framework?
There are many frameworks as well as different types of frameworks. Weather to use any at all, one, or a combination is not a simple question with a simple answer.
Frameworks range in complexity and scope. Some are do-it-all toolkits with design included, some are sensible base defaults, starting points or well laid out structures, others are add-on libraries providing useful functions or mixins. Some are more suited to consumer facing or public websites and some are better at building back-end dashboards and user interfaces.
Frameworks have some obvious benefits, and some maybe not so obvious drawbacks.
The obvious benefit is not having to re-invent the wheel — having a professionally built and tested set of reusable code to leverage.
You might also like the fact that the base design can be mostly taken care of for you, or by using templates based on existing frameworks, be able to leverage a mostly finished design.
Many frameworks are too large, too opinionated, and try to do too much. They are not always written with the best object oriented patterns or best practices or with the naming conventions you need to use. You will likely find yourself fighting with the framework’s namespacing and less than optimized specificity.
Most frameworks (especially the larger ones) do not provide a clear strategy to separate theme or design from behaviour and structure, or provide too much default design — you end up having to fight the framework providing overrides and un-setting styling. They also can try too hard to be everything for everybody, without adequately fitting your specific use case in a streamlined and maintainable way.
What promised to save development time and provide a set of sensible defaults can devolve into an unmaintainable codebase that is difficult to extend. Further pain comes in the form of the framework changing through an upgrade or re-write, potentially causing an eventual rewrite in your own codebase.
In the past I have found that while using some of the larger frameworks I’ve had to put in unnecessary effort learning the framework while that effort could have been spent writing lean and specialized code instead.
Other common complaints about using large popular frameworks are that they are bloated, and the opinionated design defaults end up making your site look a lot like a lot of other sites that are using the same framework.
The right solution
Maybe your project/team/budget/future is small, maybe you are building a prototype — maybe a large tool-kit framework such as Twitter Bootstrap is a good solution. For most serious projects however — that need to scale or be maintained over a long period of time by large teams or multiple developers — we will need to take a more strategic approach to our code and to which frameworks and libraries we embrace.
As we plan out our architecture — deciding upon naming conventions and design patterns — we will want to leverage frameworks and libraries that will not interfere with our long range goals of scalability and maintainability. There are CSS frameworks that provide a well planned and un-opinionated base set of defaults for which to build on, as well as component libraries you could piece together into your codebase and build off of, such as a grid system, and a reset.
CSS for success
As I’ve already harped on, a successful project needs to be based on a codebase that is well planned, structured, scalable, maintainable and performant. Lets touch on some of the key strategies to consider to achieve this goal.
It is important to decide on and follow a consistent set of coding styling patterns. This helps to reduce confusion, increases readability, and productivity amongst the team.
Also important is the implementation of a strict naming convention, such as BEM (Block, Element, Modifier) as well as a namespacing convention/strategy. This will fortify maintainability in the code by reducing the risk of global pollution (due to CSS’s global namespacing) as well as by making the code more self documenting. Developers should be able to look at the HTML and infer useful information about the purpose of the CSS as well as the relationships between objects and their components. This helps code reuse and successful implementation of a well planned CSS framework. It also helps to reduce CSS bloat, where developers tend to want to append new code when they cannot ascertain how changes to existing code might affect the rest of the site.
Planning out the CSS code requires visually and mentally parsing the design mockups and artwork, and building out a modular structure of sections, objects, components, behaviours and states.
Use a CSS preprocessor
Using a CSS preprocessor such as SASS helps to modularize and DRY your code with powerful features like variables, mixins, inheritance, and improving code readability with nesting.
Using Descendant selectors and selecting via native elements are the kinds of practices that create elegant code and seem like powerful CSS features to utilize, however for projects that need to scale or any non trivial project these coding practices contribute to what is commonly referred to as ‘specificity wars’. Unnecessary specificity has effects down the line where you will find yourself trying to beat out the specificity values of other existing rules. You end up adding more convoluted specific rules which make it harder to maintain a sensible organization of code — affecting maintainability.
There are strategies and guidelines we can follow to make sure we keep our specificity as low as possible, and only drawing on its powers in a strategic manner.
All of the aforementioned strategies contribute to perhaps our most important goal, achieving the best performance possible for our app or website. Users are impatient, they will leave if a page does not display quickly — apx 40% if it takes longer than 3 seconds.
These are the most likely considerations but not the only ones. Projects and their requirements vary in scope and target goals. In future posts I will delve deeper into each of these.
Need my help?
Aside from hiring me to build, improve, or refactor your front end architecture, I perform a code reviews with actionable recommendations for improvements.
Or if you have any questions about anything in my article, feel free to send me an email, I answer all emails and would be happy to help however I can.
As a result, these are the oft-chosen candidates: