New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Descendant naming #47

Closed
simonsmith opened this Issue Feb 10, 2014 · 17 comments

Comments

Projects
None yet
10 participants
@simonsmith
Member

simonsmith commented Feb 10, 2014

Should components ever have a descendant with more than one hypen? For example:

<div class="Component">
    <header class="Component-header">
        <a class="Component-header-link" href=""></a>
        <!-- Or -->
        <a class="Component-headerLink" href=""></a>
    </header>
</div>

The first example feels more correct as the hyphen denotes another child level but it also has the potential to lead to ugly class names with multiple class names.

Should the second camel-cased version be employed instead?

@jorenvanhee

This comment has been minimized.

jorenvanhee commented Feb 10, 2014

I also struggled with this. Now I just keep it simple and do it like this:

<div class="Component">
    <header class="Component-header">
        <a class="Component-link" href=""></a>
    </header>
</div>
@ferdinandsalis

This comment has been minimized.

ferdinandsalis commented Feb 10, 2014

@jorenvanhee version makes sense, since .Component-link is descendant of the component and not of .Component-header. It seems counterintuitive but HTML nesting level does not dictate component structure. I think this would overcomplicate things. BTW I struggled with this too :)

@simonsmith

This comment has been minimized.

Member

simonsmith commented Feb 10, 2014

I agree with both of you. Makes sense.

@philipwalton

This comment has been minimized.

philipwalton commented Feb 10, 2014

Limiting it to just two levels (a root and its descendants) is a great way to keep it simple, especially for the people on your team who aren't trained on the front-end. The more freedom you allow (like multiple descendent levels) the more tempting it will be for people to mimic the HTML structure in the class name, and that's definitely not what you want.

If you feel like you really need to add a second level hierarchy, or you find yourself wanting to add a modifier to a sub-element, then you might actually be dealing with nested components.

@timkelty

This comment has been minimized.

timkelty commented Feb 10, 2014

I've found a good way to think about it is how you want to deal with those styles by file, since components kept in separate files.

Consider a component, .Header with a descendant .Header-logo. If it seems like too much of a
Now you need to select an inner element of Header-logo.

If it seems like too much of a jump to create a new .Logo component and isolate those styles to file, then I'd go with .Header-logoLink. By SUIT convention, Header-logo and Header-logoLink aren't decedents, but to anyone reading it, the intention is obvious enough.

@simonsmith

This comment has been minimized.

Member

simonsmith commented Feb 10, 2014

Everyone seems to have agreed on what I thought was going to be the logical answer. I'll close this as answered. Thanks all

@Markus-ipse

This comment has been minimized.

Markus-ipse commented Oct 21, 2014

Sorry to bump this one, but I think the original question wasn't really answered, the answer @jorenvanhee provided only really applies if the links are identical all trough out the component, but what if the links should be different in the header?

Are you supposed to use a nested selector for styling the header specific links then?

.Component-header .Component-link { /** Header specific styles **/ }

Or should the header become a new component if the links in the header should have a unique style? (Which is what I think @philipwalton was alluding to)

<div class="Component">
    <header class="ComponentHeader">
        <a class="ComponentHeader-link" href=""></a>
    </header>
</div>

Actually I think the alternative @simonsmith provided when initially asking the question seems like the nicest way to do it.

<div class="Component">
    <header class="Component-header">
        <a class="Component-headerLink" href=""></a>
    </header>
</div>

But I'm not entirely sure this was the "logical answer" he referred to when closing the issue.

@lionelB

This comment has been minimized.

lionelB commented Oct 21, 2014

I also think about this alternative.

<div class="Component">
   <header class="Component-header Header">
      <a class="Header-link" href=""></a>
   </header>
</div>
@kud

This comment has been minimized.

kud commented Oct 21, 2014

It only depends on what you call a block, on what you think it's detachable or not.

<div class="Component">
    <header class="ComponentHeader">
        <a class="ComponentHeader-link" href=""></a>
    </header>
</div>

means ComponentHeader depends on Component but it's quite usable itself.

<div class="Component">
    <header class="Component-header">
        <a class="Component-headerLink" href=""></a>
    </header>
</div>

means the whole block without Component is nothing.

<div class="Component">
   <header class="Component-header Header">
      <a class="Header-link" href=""></a>
   </header>
</div>

means you really could use Header itself

<header class="Header">
      <a class="Header-link" href=""></a>
</header>

I mostly use the first solution because it's clearer for me. It means it still depends on something but I know where to place attributes like position: relative, plus, it makes like mini-blocks in a block.

In my opinion Component-header-link shouldn't exist, It should be ComponentHeader-link because the upper camelcase is enough to understand and what means Component-header-link? It's an element of an element? Nope, it's an element of a mini-block of a block, so ComponentHeader-link (where you have Component your block, ComponentHeader your mini-block, it's a child of Component but it has its own entity, and it has an element which is link).

My limit to know if it's an element or a mini-block, it's when something got too many elements, it's there I create some MiniBlock like this.

@Markus-ipse

This comment has been minimized.

Markus-ipse commented Oct 21, 2014

@kud Couldn't the third case (which @lionelB mentioned) also mean that you have a reusable Header, but when the Header is in the context of Component it would be possible to tweak it to fit the context?

e.g.

.Header {
    background-color: red;
    / ** etc **/
}
.Component {
    background-color: blue;
    /** etc **/
}

/** Should override color in .Header since it come later in the CSS **/
.Component-header { 
    background-color: darkblue;
}

/** Or if you're not entirely sure of the order of class definitions. 
This one should probably be avoided though as it increase specificity
and makes it harder to override .Header-link if it also should differ based on the context. **/
.Header.Component-header { 
    background-color: darkblue;
}
@illarionvk

This comment has been minimized.

illarionvk commented Oct 21, 2014

I agree with @kud, I use the first solution most of the time:

<div class="Component">
    <header class="ComponentHeader">
        <a class="ComponentHeader-link" href=""></a>
    </header>
</div>
@MoOx

This comment has been minimized.

MoOx commented Oct 21, 2014

I would go for

.Header {} 

.Component-header {
  background-color: darkblue;
}
@kud

This comment has been minimized.

kud commented Oct 21, 2014

If you want to use the theory of BEM, you should do like @MoOx. A tag could be an element but also a block, then you've got two classes for one tag. But in pratice, it's really boring and often useless.

Go for Component and ComponentHeader-link.

@kud

This comment has been minimized.

kud commented Oct 21, 2014

Oh by the way, the only nesting I accept is when a whole block must be modified.

.Component--active .ComponentHeader-link {
  color: blue
}

I won't add --active on every element of the block, it could be really really boring.

@simonsmith

This comment has been minimized.

Member

simonsmith commented Oct 21, 2014

If it's part of the same component then I camel case the class and stop worrying about the hierarchy in the DOM:

<div class="Component">
    <header class="Component-header">
        <a class="Component-headerLink" href=""></a>
    </header>
</div>

If the header is truly a standalone component then you could take the other approaches here but by calling it ComponentHeader you're still binding it to the parent component somewhat. Be mindful of creating a whole new component just to satisfy some unease with the way class names look.

By going this route:

<div class="Component">
    <header class="ComponentHeader">
        <a class="ComponentHeader-link" href=""></a>
    </header>
</div>

You may also need a wrapper class around the header as Components can't be styled directly in strict mode. Now you have:

<div class="Component">
    <div class="Component-wrapHeader">
      <header class="ComponentHeader">
          <a class="ComponentHeader-link" href=""></a>
       </header>
    </div>
</div>

This just feels like a lot of extra ceremony. But it depends on your situation.

@simonsmith

This comment has been minimized.

Member

simonsmith commented Oct 21, 2014

@kud I think in your example there you would use a state class, so is-active.

https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md#is-stateOfComponent

@kud

This comment has been minimized.

kud commented Oct 21, 2014

Interesting! I will see that. ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment