jquery-archive / css-chassis

An attempt at creating an open standard for both CSS and JavaScript UI libraries.
https://css-chassis.com
Other
351 stars 67 forks source link

BEM usage and modifier ordering policy for chassis classes #120

Closed geekman-rohit closed 8 years ago

geekman-rohit commented 8 years ago

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 commented 8 years ago

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...

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

sfrisk commented 8 years ago

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 commented 8 years ago

@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

geekman-rohit commented 8 years ago

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

cvrebert commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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