A modifier modifying a modifier - SUIT CSS
Now, that is a tongue twister.
So, what am I talking about after making you say that tongue twister...
Components within SUIT CSS provide a way to encapsulate CSS to a given component of HTML. As a component has the ability to be a complex item, that's where you can use modifiers
, descendants
and state
. These naming's allow for components to broken up and allow for more meaningful relationships between the CSS and HTML.
As per the docs of SUIT CSS.
A component modifier is a class that modifies the presentation of the base component in some form (e.g., for a certain configuration of the component).
All this makes sense and is easy to follow based on simple examples. You can use the --modifierName
to allow change the presentation of the base component. So in theory you could have a --large
modifier that makes the item larger. Either with padding, font or other properties.
But let's look at a more realistic example.
I am using a button
here make it a little easier to follow, and it does provide some good examples.
Based on what we know. You use a modifier to modify the base component. Lets say you have a set of designs for buttons that have different visual appearances based on size and types. Lets break down what we are trying to achieve for the button based on the designs.
- Standard button (default)
- Secondary button (secondary) - same as default with a different background color and font colour.
- Larger standard button (large) - Has different colour, font, spacing, borders.
- Larger secondary button (large secondary) - Similar to secondary, in it follows the large but with different background and font colours - even different from default/secondary.
Based on the requirements you could think about breaking this up as following using SUIT CSS
.Button
.Button--large
.Button--secondary
Makes sense. What about the requirement of the different colours. So the secondary and large secondary don't use the same background color.
This is where the point of my post comes in. One way to achieve this is for the large secondary modifier to modify the secondary. See the follow example to understand it a little easier
Modifier Solution
See the Pen SUIT CSS - Modifier - Modifier by Matthew Roach (@matthewroach) on CodePen.
Looking at the Sass, it doesn't appear to be too bad. But look at the styles in developer tools. .Button .Button--large
is overwriting all but one CSS property of .Button
. This feels like an anti pattern, even though it's not documented in the SUIT CSS docs. Also the need to explicitly set the styles &.Button--secondary
inside the .Button--large
feels messy and prone to future problems.
This also shows that .Button--secondary
is never the same in ever case which I would expect from a modifier.
Solution A
One possible solution would be to set a --default
modifier for you guess it. The default buttons. This allows the ability to have the --secondary
modifiers work a little more as intended. You are not over writing styles unnecessary. But again this still doesn't feel right that the modifiers are inter linked with each other.
See the Pen SUIT CSS - Default - Modifier by Matthew Roach (@matthewroach) on CodePen.
Solution B
Another solution which feels much cleaner. Break the Button
into multiple SUIT components. Button
and ButtonLarge
for the intended purpose and design, this allows to keep them isolated, avoid potential side effects. Keeps the CSS cleaner and consistent. And each modifier is responsible for a limited set of modifications with out needing to rely on other modifiers.
See the Pen SUIT CSS - Multiple Components by Matthew Roach (@matthewroach) on CodePen.
Conclusion
As you can see, there are many ways to achieve the same outcome. With the documentation not explicitly calling out all possible examples it can sometimes be tricky to work out the SUIT way. Now this isn't anything bad with SUIT or following a methodology.
Following a CSS methodology is a very good way to standardise and enforce rules across a team. It doesn't particular matter which methodology you decide to use, so long as it is an agreed approach. Having something in place is a good start, also using something that is well documented and has team buy in.
One of the downsides of documentation of such tools and methodologies is they are at a high level. They do not always include good examples of real examples. It's not easy to cover all examples or edge cases. This can leads to issues outlined here. A side affect to this is following a methodology can make reviewing code in a team a little more difficult. Each of the two solutions are viable solutions to the problem. But also the modifier solution presented first is something that can and will come up based on the interpretation of the documentation.
If you are working in a team where you have adopted a methodology or framework or something else where you have come up to a cross roads. Or are struggling as a team to interpret the documentation all the same way. You should document the gaps and the approaches you are taking for your needs. If possible raise questions and contribute back.