Skip to content
This repository was archived by the owner on Dec 11, 2021. It is now read-only.

BEM usage and modifier ordering policy for chassis classes #120

Closed
rohmulan opened this issue Aug 18, 2015 · 7 comments
Closed

BEM usage and modifier ordering policy for chassis classes #120

rohmulan opened this issue Aug 18, 2015 · 7 comments

Comments

@rohmulan
Copy link
Contributor

Earlier in meeting today a concern was raised while discussing #97 : How do we order modifiers for classes.

While we have decided to name classes in pattern : block_element--modifier, for most components there could be multiple modifiers concurrently block_element--modifier1--modifier2. The issue is how do we order these modifiers such that the order is easily implemented/ remembered. Since we are a css framework for js libraries, the classes should be possible( preferably with ease) via js code.

A concern was also raised if BEM is really good for our project (see #4 )? It takes more effort to code and will make things complicated for js frameworks a bit too.

Options:

  1. Deciding an order (eg. --sizerelated--state--focus etc.)
  2. Arranging modifiers in a class alphabetically. (suggested by @arschmitz )
@arschmitz
Copy link
Contributor

Option 3
Don't use actual BEM use BE M HA HA to avoid what seems to be a nightmare to construct classes with multiple modifiers we could switch from

ns-block_element--modifier1--modifier2 to ns-block_element modifier1 modifier2
This gives us almost all the same benefits of BEM as long as we avoid specificity and inheritance still.

The main issue i see with multiple modifiers in something besides alphabetical order is that for people...

  • you will always need a cheat sheet as there can be many more categories of modifiers then just size state and focus, and these categories are also component specific.
  • It will never be a reasonable expectation for people to remember the proper order of modifiers with separate classes for modifiers there is no need for this.
  • mixing up modifier order or using an incorrect modifier name has a much more serious impact. Rather then just not having the modifier take effect ( wrong name ) or no effect at al ( order ) This will now mean there will be no style at all applied to the element! Granted this is easy to see and fix as you work but still

For programatic implementation of chassis like JS frameworks or markup generated server side there are the additional drawbacks of...

  • It will be a major pain to generate class names to add to elements
    • To construct a proper class name based on options / modifiers reasonably you will need to make a special function for each element within a block that constructs a class based on the modifiers passed.
    • Some how store the information of what modifier categories an element can take and what modifers are valid in each of the categories i picture this as a giant nested array...
      • chassie-component
        • element
          • modifier-category
            • modifier
            • modifier
          • modifier-category
            • modifier
        • element
          • modifier-category
            • modifier
            • modifier
          • modifier-category
            • modifier
      • chassie-component
        • element
          • modifier-category
            • modifier
            • modifier
          • modifier-category
            • modifier
            • modifier
        • element
          • modifier-category
            • modifier
            • modifier
            • modifier
          • modifier-category
            • modifier
    • every time you want to construct a class and pass a set of modifiers this function would loop through this array to figure out the proper modifier order... pretty ugly if you ask me
  • any break in logic in this function will result in a completely broken state which is potentially not as easily noticed ( edge cases ).
  • For JS frameworks making components where modifiers need to be added and removed at run time you have the added complications of...
    • needing to query the current class on the element parse it to figure out what modifiers it currently has.
    • rectify this with whatever you need to add or remove
    • Generate new class with new modifier set
  • This seems like an awful lot to ask of a framework wanting to use chassis how can we justify all this extra effort over continuing to use custom themes or using something else with an easier structure

@sfrisk
Copy link
Contributor

sfrisk commented Aug 19, 2015

To expand on option one:

Using the argument "you will always need a cheat sheet" if there are more modifiers than size, type, and state, is like saying you always need a cheat sheet if for a javascript function passing in variables.

Since the concern is for Javascript Frameworks, let's use JavaScript terminology. We have a function called uiButton. uiButton has a bunch of arguments that can be passed to it, for example "size," "type", "state", "corners", and whatever other features this button may have.

so we have:

function uiButton ( type, size, state) {
   // code to render button here
}

It's already been pre-determined that type has four different states it could possibly be in ("info, warning, error, danger"), size has four different possible sizes ("extra-small", "small", "medium", "large"), and a number of different states (focus, active, hover, disabled).

So let's say we have two buttons. One button has the arguments (info, small, active), while the other button has (warning, large, focus). In the current naming scheme we have with the buttons PR, the order of the modifiers for the buttons would be:

ui-button--type--size--state

with the ui-button being the element and type, size, and state being the parameters being passed into it, so the two buttons in the example above would be something like this:

.ui-button--info--small--active
.ui-button--warning--large--focus

However, if we go with something like option 2 which all modifiers are listed alphabetically we get something like this:

.ui-button--active--info--small
.ui-button--focus--large--warning

In JavaScript, we don't reorder the parameters of a function just because the value of the variable has changed, and doing so here would potentially overcomplicate the codebase and complicate the documentation associated with this project.

To apply this to CSS terminology, we don't order the margin of a css attribute by ascending order, from least to greatest number, instead margin' has a number of values that may be passed to it, and if four values are passed to it, we know that means top, left, bottom, and right - in that order.

The above being said, I'm fine with doing something like option number three, although I think option one wouldn't be too hard to achieve if we clearly define what the different parameters/modifiers are of an element, what are acceptable options of each of those modifiers, and after that, a lot of the code could be generated via mixins. It would mostly involve having a bit more discussion/planning ahead of time before tackling major css components.

@arschmitz
Copy link
Contributor

@sfrisk actually too many parameters would be considered bad code smell in JS for example with button there is more then just size, type, and state you would also have AT LEAST corners and display ( block vs inline ) a function with 5 parameters is generally considered very undesirable and would be changed to use an options object where order does not matter and you can exclude arguments because both remembering the order and being forced to pass all params is not desirable from a usage / user perspective.

in JavaScript, we don't reorder the parameters of a function just because the value of the variable has changed

Thats not true things like this happen all the time. Look at most jQuery methods the parameters and order change based on whats passed for connivance based on the typeof of the arguments. examples:
http://api.jquery.com/prop/
http://api.jquery.com/off/
http://api.jqueryui.com/jQuery.widget/
http://api.jqueryui.com/jQuery.widget/#method-_on

@rohmulan
Copy link
Contributor Author

I like the option 3 @arschmitz suggested. It will be easier to both code and later maintain.

@cvrebert
Copy link
Contributor

I likewise agree that something like Option 3 is the way to go. Trying to cram all the modifiers into one class like Options 1 & 2 makes twiddling one of the modifiers via JS rather annoying to do. And the CSS would have lots of redundancy. Bootstrap uses a scheme similar to Option 3 and it has served us quite well in practice.

So taking the button example, it might look something like:
<button class="ui-button ui-button--warning ui-button--large ui-button--focus">
(I would quibble about the "button" token being kinda long given that it's now repeated a few times, but that's drifting off-topic.)

@maikuru
Copy link

maikuru commented Sep 2, 2015

If one was using javascript to generate the element;

//defaults defined somewhere else
var myOptions = {
  state: "<value>", // => active | focus | disabled | etc...
  size: "<value>",  // => small | medium | large | etc..
  positioning: <value>, // => inline | block | etc..
  stateChanged: <callback>, //optional method called whenever the state changes
  label: "<value>",
  etc...
};
var myButton = uiButton('info', myOptions);

From the JavaScript developers perspective they don't give a flip about the order of the class modifiers name. They want an API they can call to set/get those properties.

It's the CSS Developer/implementer that cares about that and they want consistency, which can be handled using the SASS mixins. There is no reason to modify the order in which these properties are rendered the class names. That only makes the mixin's more complicated and makes hand-coding the CSS a pain in the ...

@sfrisk
Copy link
Contributor

sfrisk commented Dec 1, 2015

Between this and Chassis Meetings, Option 3 is a go.

@sfrisk sfrisk closed this as completed Dec 1, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants