📜 ⬆️ ⬇️

Cyclomatic complexity: CSS logic

Over the years, we have argued that there is no logic in CSS. Thus, we wanted to say that there was no flow of control or a way to program them to program. This inherent flaw in logic was used as an argument in favor of using processors (to provide this missing function), and as an argument against preprocessors (CSS never implied logic, so we should not try to implement it).

Recently, however, I was confronted with a thought that made me realize that CSS actually has logic, and the fact that it is rarely seen as such, probably is the reason why we get CSS as a whole rather weak.

I found that I explain to the client complex selectors, as if they consist of a subject — the thing we are actually interested in — and its conditions. For example:

div.sidebar .login-box input.btn span { } 

In this complex selector, the subject is a span, and its conditions are IF (inside .btn) AND IF (in input) AND IF (inside .login-box) AND IF (inside .sidebar) AND IF (in div).
')
 @if exists(span) { @if is-inside(.btn) { @if is-on(input) { @if is-inside(.login-box) { @if is-inside(.sidebar) { @if is-on(div) { # Do this. } } } } } } 


Probably not. It looks too crooked and confusing. Probably, we would have done better like this:

 @if exists(.btn-text) { # Do this. } 

Every time we insert or define a selector, we add another if statement to it. This in turn increases what is called cyclomatic complexity.

Cyclomatic complexity


In programming, cyclomatic complexity is an indicator that refers to the number of “moving parts” in a code. These moving parts are usually points in a particular control flow (if, else, while, etc.), and the more of them we find, the greater will be our cyclomatic complexity. In fact, we need the cyclomatic complexity to be as small as possible, since greater complexity means, among other things, that:

• The code is more difficult to evaluate;
• There are more potential points of error;
• The code is more difficult to change, maintain or reuse;
• You will have to consider a greater number of results and side effects;
• And the code is much harder to test.

With regard to CSS, we mainly look at the number of decisions that the browser must make before it can or cannot execute something. The more if statements in our selectors, the higher the cyclomatic complexity of this selector. This means that our selectors are more fragile, since they have more conditions that need to be fulfilled for them to work at all. This means that our selectors are less obvious, because the inclusion of if statements may not necessarily lead to erroneous positive matches. This makes our selectors much less reusable, as we make them jump all the way more than necessary.

Therefore, instead of being attached to the span inside .btn (and so on), we better create a new class .btn-text, to which we will be attached. This is a more direct way, as well as a more concise and rational (a large number of @if leads to the creation of fragile selectors, which are more likely to fail).

The trick is to write selectors the way the browser analyzes them: right to left. That's why you need to define a span with a lot of conditional constructions: to narrow the scope of the selector. You need to start from the other end; write something unambiguous and understandable, and completely give up the conditions.

Instead of your selectors initially grabbing a huge amount of DOM elements, then to reduce coverage through conditions, it’s best to just capture a lot less DOM elements.

Cyclomatic complexity is a rather interesting principle that can be used in CSS, but if we look at it only as a principle, we can begin to visualize and even measure complexity in “logic” and, based on that, start making better decisions.

A few rules:
• Treat selectors like mini-programs: every time you type or define something, you add one if statement; pronounce all these if out loud to keep selectors simple.
• Try to keep minimal cyclomatic complexity: use a tool like Parker to keep track of your selectors in terms of cyclomatic complexity.
• Minimize the use of nested selectors: sometimes an attachment to CSS is necessary, but in most cases it is not. Excellent article on this topic.
• Start looking at selectors from right to left: start with an element you are sure of, and then write a minimum of additional CSS to get the right fit.
• Finalize the assignment of the selector: make sure that you write the selectors that you want, and not just those that turned out to be working.

Your selectors are a major aspect of your CSS architecture. Make sure you make them sensible and simple.

Source: https://habr.com/ru/post/257101/


All Articles