In one of our previous blog posts, we’ve already described Object Oriented Thinking and objects theory. But what if indivisible objects are not enough to have decent organization and structuring? Assembling application together from the huge set of atomic objects is not so easy. If your app has a quite rich UI and your objects library looks like subway station in morning peak hours — most likely it is time to consider building modules.
Defining a module
Module is a unique composite component that consists of objects. In other words, this is an object made from objects. It’s easier to think of modules from the atomic physics analogy where objects would be atoms and modules – molecules.
Modules necessity
Module usage might seem non-evident and doubtful considering that separation objects and modules appear to be complex and not-so-obvious.
It is much easier, however, to maintain and support objects united by certain principles into something bigger.
Let’s say we have a simple form:
Evidently, each of the three elements is an object:
But at the same time we understand that the contact form can be treated as an object itself: it is consistent, simple, independent, and can be reused without any modifications. Therefore, it’d be logical to have it as an object for easy maintenance and re-use. The only difference is that it’s divisible; and this will be the main distinction between modules and objects.
Modules modifiers
Modifying modules follows the same logic as modifying objects. If you need to modify a module, do it with the modificator class name.
For example, below is a variation of the form we’re already familiar with:
It’s easy to see that structure is the same and appearance makes the only difference. So, we add a modificator class:
and corresponding style rules which will add appearance guides or override the default ones:
.form.muted { background-color: #fff; } .form.muted input[type=text] { background-color: #ebebeb; } .form.muted input[type=submit] { background-color: #262626; }
Please note there is a specific aspect here: it may be hard to outline a modification target – module or object.
If you see that a requested change is definitely related to the whole module, then this module is what should be extended with modification. But it’s easy to miss the fact that it’s objects that should be modified instead of the whole module.
Back to our example, we have two variations of inputs: grey-backgrounded and white-backgrounded.
So, most likely, there are two possible scenarios:
- The only place where different inputs are present is two contact forms.
These are the circumstances for module modification, exactly like described above. - Or, on the contrary, they can be found throughout the whole app within many cases.
In this case we should modify object(s) itself, not the whole module (form):
input[type=text].muted { background-color: #ebebeb; }
input[type=submit].muted { background-color: #262626; }
Module selectors nesting
Coding modules should not make you write much more complicated code that simple objects do. This means that depth of selectors nesting should not reach more that ~3-4 levels deep.
Getting deeper than that may result into one or more of following:
Overcomplicating a module
It’s a common case when module continues to grow iteratively and it’s hard to pick the moment when it grows out from the cradle. But keep an eye on it. Unwatched module can become a trouble-making monstrosity. Just consider to break the module into a few smaller ones.
Modifying a module instead of creating new objects
The case that we’ve described in the forms example above. What should I modify: module or objects? Module stylesheet size and complexity can be a hint here.
Redundant helper wrappers
The case where you put some wrappers and they migrated to css selectors making them inexplicably long. Note that css rules should include only structural dependencies.
I.e., you have a section with inner div and object inside it:
And rules for the button should be declared like this:
.section input[type=submit] { ... }
Instead of:
.section .section-wrapper input[type=submit] { ... }
Moreover, you can consider removing non-structural wrappers and moving their appearance to :before
or :after
pseudoclasses. This approach will make your structure clearer and should help eliminate the problem with selectors chain described above.
Conclusion
Modules are just an extended OOCSS approach which helps to keep code structured and well-organized. Most of its benefits are felt on large products where simple objects can be combined together in modules. In this case, modules can really help you keep your code easily extendable and scalable.