How to use pseudoclasses with BEM?

Viewed 543

How do I use pseudo-classes efficiently, while following BEM methodology?

My specific example is the following - I need to create a checkbox functionality with a custom look. For that, I normally would use input:checked + label selector. I'm trying to convert this to BEM, but the best I can do is:

CSS:

/*.custom-checkbox 
{
}*/

.custom-checkbox__input
{
    display: none;
}

.custom-checkbox__input:checked ~ .custom-checkbox__box-label
{   
    background-image: url("../../images/pro/check.png");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 100%;
}

.custom-checkbox__box-label
{
    width: 1.4rem;
    height: 1.4rem;
    position: relative;
    top: 0.2rem;
    
    display: inline-block;
    background: white;
    border: 0px solid;
    border-radius: 0.2em;
}

.custom-checkbox__box-label:hover,
.custom-checkbox__txt-label:hover
{
    cursor: pointer;
}

HTML:

   <li class="custom-checkbox">
     <input class="custom-checkbox__input" type="checkbox" id="distinctcat_cb1" checked>
     <label class="custom-checkbox__box-label" for="distinctcat_cb1"></label>
     <label class="custom-checkbox__txt-label" for="distinctcat_cb1">Categories</label>
   </li>

this contradicts BEM due to sibling selector (~). Also, I'm not sure about pseudoclasses (:checked, :hover) with BEM in general, are they allowed or not? Are pseudo-elements (:first) allowed? For some reason they are not mentioned in any BEM guides I could find.

What would be the best practice for making a custom checkbox with BEM?

1 Answers

One of the main reasons, if not the most important one, why BEM was created was to have blocks, which you can place almost anywhere within your frontend without having to bother about the class hierarchy or any kind of style depending on class nesting.

Thus when you express a certain element behaviour within a block like with some kind of checkbox hack

.custom-checkbox__input:checked ~ .custom-checkbox__box-label

it's not only the only way you can achieve that behaviour, it's also within the bounds of the BEM convention.

And the reason for this is: as long as you can move your "custom-checkbox" block anywhere within your code without any behaviour or rendering change, you are still honouring the BEM principle.

Also, anyone reading your code, can immediately understand that you are going for an element manipulation on the box-label element depending on the state of the input element within the custom-checkbox block.

Your code is readable and it expresses the block => element structure.

The BEM rule which says you should not nest classes i.e. not make behaviour depending class relations does not apply to your case, because you are not creating a relation between two nested class entities.

You are good to go.

Related