Comments (9)
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.
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.
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.
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.
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.
@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:
- 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. - 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 toButton is-error
. - 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.
@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.
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.
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)
- Animations HOT 2
- Styles for export - best way to override compoents and/or their modifiers HOT 7
- * Span in Radicar
- Best method for handling same nested block with different modifier? HOT 3
- What lock files we should keep? HOT 11
- Update naming of variables to comply with new conventions HOT 3
- What's next for suitcss? HOT 19
- Monorepo HOT 25
- How about A Chinese documentation? HOT 1
- Remove Component(1) Installation Reference HOT 2
- Upgrade to Node 6 HOT 2
- When using glob @imports, `postcss-reporter` incorrectly reports stylelint errors HOT 4
- Webpack HOT 4
- How to add --xl-viewport HOT 3
- Kill preprocessor HOT 2
- Consider dropping IE10/11 support? HOT 1
- Theming
- Any alternative to html-inspector?
- Nice - I'll send a pull request. Thanks. HOT 3
- What's the difference between a modifier and a state? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from suit.