Code Monkey home page Code Monkey logo

Comments (9)

timkelty avatar timkelty commented on August 24, 2024

I agree, this usage is tempting.

.Button.is-primary carries with it a greater specificity than .Button--primary, which may not be desirable. In most cases, though, I think it is pretty manageable.

from suit.

jorenvanhee avatar jorenvanhee commented on August 24, 2024

I think it's easier to see what's related to each other if you use the Button namespace for instance. What if you have two objects with modifiers on an element. I know this is rare, but how will you know what's what.

from suit.

philipwalton avatar philipwalton commented on August 24, 2024

I can see it both ways (and have wrestled with this question myself on occasion). But at the end of the day I think there is value in separating (via a naming convention) styles that modify components at load time verse styles that modify components at runtime via user interaction.

I wrote about this issue a few months back; here is an excerpt that summarizes my argument:

JavaScript can ... also add or remove classes to change the style of elements. But this can be a problem if those classes aren't identifiably different from the classes that appear on page load.

When JavaScript code knows too much about component styling it becomes very easy for a CSS developer to make changes to a stylesheet and not realize he's breaking critical functionality.

This is not to say that JavaScript shouldn't alter the look of visual components after the user interacts with them, but if it does it should do so through an agreed-upon interface. It should use classes that are identifiably different from the classes that define the default styling.

At the end of the day I think this is a question of maintainability verses learning curve, and for smaller teams you can probably get away without the distinction. For larger teams where the person writing the JavaScript isn't also the person writing the CSS, I think it's helpful to keep the codebase predictable.

If you end up choosing to just use one or the other, I'd strongly recommend sticking to the BEM-style modifiers over the SMACSS-style state classes.

from suit.

AntonTrollback avatar AntonTrollback commented on August 24, 2024

I tested this in a medium-size project.

It's nice, but the specificity changes is a deal breaker. Ended up using the modifier syntax in some cases and would not go down this road again.

from suit.

necolas avatar necolas commented on August 24, 2024

I tested this in a medium-size project.

Nice! That's a good way to try things out. Thanks for the suggestion and everyone's feedback.

from suit.

simurai avatar simurai commented on August 24, 2024

@AntonTrollback Do you still remember the details about "specificity changes is a deal breaker"?

Because I've been toying around combining modifiers and states, like you suggested. Yes, it would increase specificity for modifiers, but on the other hand:

  1. No repeating of the component name. Button Button--primary is fine, but sometimes they can become pretty large and it gets harder to read the inspector.
  2. Peace of mind. You wouldn't have to think what is a state and what is a modifier. Or if a class exists on load or get changed/added at runtime. The line can also be blurry. For example if you click on a button and an error happens and the button should turn red, is that a modifier or a state? With the is- prefix it wouldn't matter. Button is-primary would be switched to Button is-error.
  3. Now that CSS variables use the double dash, it clashes a bit with the modifiers. I mean just visually .Button--error { color: var(--error-color) }

Well, I might give it a try and see how this specificity thing behaves.

from suit.

philipwalton avatar philipwalton commented on August 24, 2024

@simurai I'm starting to think more and more about removing this distinction as well. However, I'm leaning the other way, toward a more traditional BEM implementation that only uses modifiers.

My concerns are about transitioning to a future with Web Components. With pure BEM there is a 1-to-1 relationship:

  • Block == Custom Element
  • Element == Shadow DOM subtree element
  • Modifier == Attribute on the shadow host

In this paradigm there isn't much of a distinction between state and modifier, so I think doing away with the distinction may be more future proof. That being said, this idea has definitely not been tested in a real app...

from suit.

necolas avatar necolas commented on August 24, 2024

We're using state classes to control presentation when the state of a component changes. The extra specificity is useful for extension / customization contexts. Easier to think about this in React-like terms. Pseudo-code example:

I have a basic TweetAction definition:

<button class="{$props.className} TweetAction {$local.state}" aria-label="{$props.type}" type="button">
  <Icon class="TweetAction-icon" name="{$props.type}"></Icon>
</button>
.TweetAction {
  color: lightgray;
}

(A) if I use modifiers only:

.TweetAction--favorited {
  color: orange;
}

(B) if I use state:

.TweetAction.is-favorited {
  color: orange;
}

I want to make an action bar that I'm going to display on a dark background, so the actions needs to be white by default:

<div class="{$props.className} TweetActionsBar" role="group" aria-label="Tweet actions">
  <TweetAction class="TweetActionsBar-action" type="reply" tweet="{$tweet}"></TweetAction>
  <TweetAction class="TweetActionsBar-action" type="favorite" tweet="{$tweet}"></TweetAction>
  <TweetAction class="TweetActionsBar-action" type="retweet" tweet="{$tweet}"></TweetAction>
</div>

If I can only use modifiers (A), then the following CSS overrides the favorited state color too, even if I have no intention of doing so:

.TweetActionsBar-action {
  color: white;
}

But by using state classes (B), it is preserved, but you can still replace it if you intend to (notice how this is still a "valid" selector within the context of the TweetActionsBar CSS file):

.TweetActionsBar-action.is-favorited {
  color: yellow;
}

In this particular example there is a way to side-step the issue by letting the default color be inherited from the calling context. But a Button or other more complex components won't have that. If I want to extend a Button and make some style changes to the default styles, I might end up replacing the pressed state, disabled state, etc..

I'm still finding state useful for these reasons, basically extending components and making dynamic changes less likely to be unintentionally replaced. Having said all that, we use state presentation quite sparingly: open/closed dialogs, tweet action states, buttons / controls.

I don't think it will be incompatible with Web Components because IIRC they will supposedly provide a better, native way to define which nodes and styles can be altered from the outside context.

from suit.

philipwalton avatar philipwalton commented on August 24, 2024

I don't think it will be incompatible with Web Components because IIRC they will supposedly provide a better, native way to define which nodes and styles can be altered from the outside context.

Yes, in Web Component land there is the :host-contenxt() pseudo-class, so you could do something like this:

:host-context(.is-favorited) {
  color: yellow;
}

from suit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.