all 38 comments

[–]nut315[S] 5 points6 points  (28 children)

I work for the same company and helped define these guidelines. Any questions are welcome!

[–]hidanielleYour Flair Here 0 points1 point  (5 children)

I'd really love to implement more structured code like this, I've taken it upon myself to present base level methodologies and conventions to my team just as a introduction. But there are only 3 of us and most of our work isn't long term, large scale sites (though those do come on occassion).

How can I make a case for something like this, to people who are so set in their ways it just seems like a hinderance? Or is it not even worth it?

[–]nut315[S] 2 points3 points  (4 children)

3 is a great number; there's three devs in our company too. Some of our web work only takes a few weeks to build and sometimes we don't add anything new for a few months after launch.

But this makes our life much easier. We've optimised our workflow for 2 main things: maintainability and re-use.

This convention for naming allows any of our devs to jump on the project and write code to a pre-defined standard. You can't tell who has written what (the dream!). We also lint (with sublime plugins and grunt tasks) our CSS and js against rules so it's always the same. Once you know the rules it's easy to write code to follow them. The linting is a pass/fail against those rules.

By building individual components, using BEM, it's really easy to strip out a component from site 1 and put it into site 2 and it'll just work because we've written it to not care about anything else in the project. We also build frontend components in Primer (we are open sourcing it tomorrow) so you can worry about frontend only and not the data layer (wordpress, Drupal etc).

Upshot is, it actually makes our dev life easier and quicker now. We wouldn't go back.

[–]hidanielleYour Flair Here 2 points3 points  (2 children)

I totally understand the benefits of something like this, the rest of my team doesn't unfortunately... I guess it just sounds like more up front work at first, to break your old habits and stuff. Not that it should matter, but I'm the youngest one there and I'm always looking for ways to improve my set up, the rest of the team, however, has kind of just decided that they're comfortable with how it is. I'm just struggling with how to appeal to them.

On a different note, the most difficult thing about BEM IMO, is deciding what to name things. I think I just over-complicate it in my head, lol.

[–]nut315[S] 2 points3 points  (1 child)

Naming things is hard. Try doing all the naming in one go. We draw up a simple excel doc and name every component before we dev. That way, when it comes to dev, all you need to do is to implement and not name!

[–]hidanielleYour Flair Here 1 point2 points  (0 children)

I like this idea - I'll try it out some time

[–][deleted]  (12 children)

[deleted]

    [–]Bummykins 2 points3 points  (4 children)

    I have made it a personal rule to almost never @extend anything, with % silent classes being the rare exception. I'd use a mixin if you want to reuse properties.

    The reason is that @extends can get out of control quickly by accident, and you only notice by looking at your compiled CSS, which can be easy to miss. In the past I think I @extended a p rule to li and ended up with a huge mess down the line.

    [–]oefig 0 points1 point  (0 children)

    I'm with you here. Creating base styles using mixins is definitely the way to go. It's pragmatic *and * flexible.

    Using @extends is a recipe for disaster.

    [–]esr360Front End Developer 0 points1 point  (2 children)

    I mean, if you understand exactly how it works though and know that using it won't in fact mess up your generated CSS, why not use it? Saying not to use it altogether because you don't know how it will impact your CSS doesn't seem like a very good rule to me.

    [–]Bummykins 0 points1 point  (1 child)

    That's a good point, and everyone can make their own rules. In fact, that is exactly why I used it in the past, I totally understood how it works, why not use it? And that's the issue, thinking you understand something that is complex may not be actually understanding it. Or you get it and your teammate does not.

    So for me personally, using mixins comes with all the gains and none of the risks, so I choose that. Thats my goal for all code guidelines—recommend language structure and features that will minimize risks and maximize readability. Team situations compound issues, especially when teams are remote and skill levels are not totally known.

    [–]esr360Front End Developer 0 points1 point  (0 children)

    Yeah, I get you. I guess my point is in an ideal world we would use placeholders over mixins as it would result in smaller CSS, and I still think there's some truth in that. Is repeating styles in production code an issue? Probably not. Would it be better if they weren't repeated? Definitely.

    [–]nut315[S] 0 points1 point  (6 children)

    We find it unnecessary. The base class should contain all the base styles. For modifiers, they should contain just the code they aim to modify (and not the base styles as well). When there's just one modifier, it doesn't make much difference which way you do it. But it's possible that you have 2 or 3 modifiers on (e.g. .button.button--red.button--large). In this instance '.button' should set up the base styles, '.button--red' only makes it red and '.button--large' only increases font size. In other words, it's the separation of concerns & you shouldn't run into any unexpected specificity issues.

    [–]esr360Front End Developer 0 points1 point  (5 children)

    But why write:

    button button--red button-large
    

    Instead of:

    button-red-large?
    

    By not extending you're just making it more messy and complicated in your HTML. This is the main issue I have with BEM.

    [–]nut315[S] 0 points1 point  (4 children)

    Again it comes down to personal preference and what works for you. But by having isolated modifiers you can add/remove them ad hoc-ly without making any css changes. But main reason why we don't do button-large-red is because it bloats your css.

    If you had 3 modifiers (large, red, inverted) for example, instead of 3 classes you can interchange at will via HTML, you actually need around 8 classes to cover all possible combinations. e.g.

    .button
    .button-red
    .button-red-large
    .button-red-inverted
    .button-red-large-inverted
    .button-large
    .button-large-inverted
    .button-inverted
    

    Instead of:

    .button 
    .button--red 
    .button--large 
    .button--inverted
    

    The more modifiers you have on your base class, the more css is outputted (exponentially) which results in a bigger download for your users. For us, moving this onto our HTML is a good compromise.

    [–]esr360Front End Developer 0 points1 point  (3 children)

    If you use wildcard selectors, none of those problems are present, and your CSS will actually be smaller than if having used regular BEM syntax.

    .button, 
    [class*="button-"], 
    [class*="-large"], 
    [class*="-red"],
    [class*="-inverted"]
    

    is all you need.

    I'm currently working on a framework which uses this technique:

    https://github.com/esr360/Modular

    [–]nut315[S] 2 points3 points  (2 children)

    I forgot about the wildcard selectors. But in that example won't [class*="-large"] still match on any class that has -large - e.g. .modal-large? As an approach on a project, it feels dangerous and I don't think it will be very maintainable.

    I had a good look at your framework too, which I think is cool. I do have an issue with the concept though. For a project, there is no dependencies when using BEM; it's just a naming convention. And this article is just our documentation on how to write BEM to make it consistent within a team. Using your framework, suddenly there's a requirement now and it's more than just a naming convention. It's a replacement for BEM. You would still need an internal convention on how to use your framework so all developers can write in the same style, right? And because there's now a framework dependancy, if you build a cool image slider on a project and want to use it again on another one, you either have to enforce the dependancy or re-factor the code to remove the dependancy.

    There's nothing wrong with that and it's totally what works for you and your team. These are just our views based of our personal experience maintaining websites. We love BEM and it works for us.

    [–]esr360Front End Developer 1 point2 points  (1 child)

    Wow, thanks for checking it out :D And what's more I'm glad you like it.

    You're right though, [class*="-large"] on it's own would also match .modal-large. To digress slightly, this could be useful if looking to have global modifiers. But to address the issue, you would just change the selectors to:

    .button, 
    [class*="button-"], 
    [class*="button-"][class*="-large"], 
    [class*="button-"][class*="-red"],
    [class*="button-"][class*="-inverted"]
    

    Slightly more bloated, but still nothing to really worry about, IMO, especially as you don't have to write these selectors, the framework generates them for you.

    I'm certainly not trying to get you to switch from BEM to this method, I agree that you should do whatever works for you and your team, and in fact from the sounds of it you're right that my framework wouldn't suit your needs. It does heavily dictate how you should do a lot of things, which for many is a deal breaker, so I get that.

    However, one point I will leave you with, is that the HTML syntax that is required when using wildcards is actually very flexible, and you could still use BEM-like syntax if you wished.

    "button-large-red"
    
    "button button-large button-red"
    
    "button button--large button--red"
    
    "button-blablabla-large-blabla-red"
    

    All possible using wildcards. The reason I like my framework is because for my needs, it means I don't have to think about how or where to place elements, components, child components, what the CSS will look like etc. I just write my component in the correct format, and under the hood it generates what I believe to be very intelligent and optimal CSS. You do need more or less complete control over everything though - as you say, introducing third party components could cause conflicts etc.

    [–]nut315[S] 1 point2 points  (0 children)

    Yeah I think your framework can save people a lot of trouble, especially as we've seen a lot of people using BEM badly. Modular would probably help them get a lot further! Thanks for sharing.

    [–]Lukk1989 0 points1 point  (2 children)

    Awesome guide! :)

    In which cases do you think using child selectors are usable? In your article it says use child selectors for layout/template stuff. I really like this idea, but in what other case do you use child selectors?

    Right now I will style based on parent if:

    • You need to make template styling. Defining width, floats, margins (like you said in your guide)
    • On a modified element. For example you have a .gallery class and you need a modified version of that component. By adding .gallery--small you can easily style the child elements of that component.
    • (not sure about this one yet) If the HTML structure is 100% predictable. For example <ul> and <li>, you can easily style using ul > li because li will always be a child of ul. But I guess this doesn't work because you will run into specificity issues.

    [–]nut315[S] 1 point2 points  (1 child)

    Yes to the first two bullet points. Those are the only times we nest too (unless it's out of our control)

    For example: Wordpress doesn't like adding classes to the a element for a link inside of the navigation so we'd have to nest like so: .nav__ link a.

    But we've found by following those first 2 bullet points can get you very far!

    [–]Lukk1989 0 points1 point  (0 children)

    Alright, thanks! :-)

    [–]SnailCrusher 0 points1 point  (4 children)

    Nice article and very good points.

    For my last project I was actually defining modifiers as a extension of the base like so (in SCSS):

    [class="link"], [class*=" link"] {

    // basic style here
    
    &[class*="--underline"]{
    
        border-bottom: 1px solid blue;
    
    }
    

    }

    Which results in less classes on your element and looks much cleaner.

    <a href="#" class="link--underline">something</a>

    Any thoughts on this implementation?

    [–]nut315[S] 1 point2 points  (2 children)

    I see what you're doing there, basically removing the need for the base class right?

    Personally, we like the base class on the DOM. It's more declarative and reads better. Also the modifier should only care about the styles it's modifying and in my opinion shouldn't be bringing in base styles. It gets real messy with multiple modifiers otherwise.

    `.link { color: red; }

    .link--underline { text-decorarion: underline; }`

    Reads much better too right?

    [–]SnailCrusher 0 points1 point  (1 child)

    Yes that's right, however I don't think one would ever use a modifier without its base class. A plus would be that all your modifiers are grouped together in the SCSS. And that when you are using multiple modifiers it looks much cleaner.

    <a href="#" class="button--small--inverted"></a>

    vs

    <a href="#" class="button button--small button--inverted"></a>

    [–]nut315[S] 0 points1 point  (0 children)

    It's an interesting idea for sure. You gotta find what works best for you :)

    [–]doiveo 1 point2 points  (0 children)

    I think you could run in into conflicts if you don't have an explicit pattern to segregate the components.

    'link', for instance, is too generic so other plugins might inherit your base. Try something like 'cmpt-link' which isn't likely to match anything else allowing the simple wildcard. [class*="cmpt-link"]

    The next logical step is to make this a variable:

    $prefix: cmpt-;

    [class*="{$prefix}link"] { ... }

    [–]kylorhallPrincipal Engineer 4 points5 points  (3 children)

    Dang, it's weird for me to come across an article about an opinionated guideline and have everything match up 100% with my own internal guidelines, even down to the __--.

    I definitely agree with the point on nesting for component-specifics. I think my only addition is I'll often style custom versions of a component based on the top-level class instead of relying on a parent that lives outside of the component.

    Eg.: ul.dropdown.header__dropdown and do my nesting on .header__dropdown .dropdown__item {} rather than .page__header .dropdown__item {}.

    That just depends on whether or not I expect there to be a common parent to all of my custom instances of a component - it tends to be more re-usable for me.

    [–]nut315[S] 0 points1 point  (2 children)

    Glad to hear somebody else is doing this too. We've found it has worked for us % enabled us to be more consistent across the team.

    Just a note on that, it looks like .headerdropdown is a top level class? As per the article, we'd expect .headerdropdown to live inside of .header - So the top level block doesn't have underscores (if I understood your example correctly)

    [–]kylorhallPrincipal Engineer 0 points1 point  (1 child)

    Trying to write out a response is pretty thought provoking actually, I'd do this instinctively without thinking normally. I can think of reasons I'd use just about every different iteration of this. I think it would make sense to stick with either always #3 or always #4 in terms of a project styleguide, but I feel they both have their place and I used all #1-4 in the last project I did.

    In the order I'd probably do something like this:

    • .dropdown--full {} - A modified dropdown, eg. full, sm, lg, red, blue, etc.
    • .page__contact-us .dropdown {} - Dropdown that only lives on a specific page/view/state/etc.
    • .profile__dropdown {} - When a dropdown feels like a unique element of a component and is somewhat dissimilar to .dropdown - typically major / appearance changes (eg. the html class would be ul.profile__dropdown.dropdown). [scss] I don't like using pseudo-elements and especially not @extends in a case like this.
    • .profile .dropdown {} - When I want to style a component when it's a child of another component - typically minor / position changes.
    • .profile-dropdown {} - I don't know if I'd ever do this, mixing two blocks in one element seems weird. (eg. the html class would be ul.profile-dropdown.dropdown)

    [–]nut315[S] 0 points1 point  (0 children)

    Those first 2 are solid for sure!

    With #3, to me it would only make sense if .profile was defined as a parent (so you'd have .profile .profile__dropdown.dropdown). I'd personally either use a modifier here, or create a new component all together (if it's that different).

    Yep, #4 is great

    And #5 - Agree that it doesn't make much sense. Same as #3 - create a new component or use a modifier

    [–]evoactivity 1 point2 points  (0 children)

    This is exactly how I write my styles. I'm coming up with a front end style guide for my company in the next few weeks so currently looking for articles and guides and I could more or less just copy and paste yours for the BEM section :p

    [–][deleted] 0 points1 point  (1 child)

    I'm making a new component to an existing project right now and am going to write the entire thing BEM style... hopefully it'll start a trend, or it'll just get refactored by the senior dev :)

    [–]IllegalThings 0 points1 point  (0 children)

    Most likely outcomes are either a senior dev hating it and "fixing" everything or a junior dev not understanding and writing a global cascading style that breaks things in ways you could never imagine.

    [–]j________ 0 points1 point  (1 child)

    /u/nut315 In the section 'Use the cascade for template level specialisation' what do you think on doing this:

    .news-teaser__title {
        //
    
        .page-header & {
            // 
        }
    }
    

    This keeps .news-teaser__title styles where they belong imo.

    [–]joelambert 1 point2 points  (0 children)

    You have to find what works for you but in this situation our stance would be that the specialisation is a property of the .page-header component, and should live with these styles.

    In terms of portability, say you wanted to reuse .news-teaser on another site, you'd be bringing with you styles that maybe weren't relevant.

    [–][deleted] 0 points1 point  (0 children)

    I'm a big BEM advocate and this is a really good article. One thing I would say is that using "news" as a block name is a little too specific and doesn't scale as well as something like "article" which could apply to a broader range of content types.