postcss-extend icon indicating copy to clipboard operation
postcss-extend copied to clipboard

Possible to extend a subclass?

Open Blindmikey opened this issue 9 years ago • 4 comments

Scenario: Extending a BEM type of modifier directly

%button {
    & { ..A.. }
    &:hover { ..B.. }
    &.-large { 
        & { ..C.. }
        &:hover { ..D.. }
    }
}

input[type=submit] { @extend %button.-large }

I expect an output of

input[type=submit] { ..C.. }
input[type=submit]:hover { ..D.. }

But I only get

input[type=submit] { ..C.. }

Is there a way to achieve what I'm after, is this a bug? Or is this an intended limitation?

Thanks!

Blindmikey avatar Dec 17 '15 04:12 Blindmikey

It is a limitation, intended without consideration for the consequence. Most of the test cases and uses don't go looking down nested (even if they're BEM) rules for types like :hover

It's not something I considered in the original use case, and I'm a bit curious how hard it would be to implement - I'll look into doing it, but for now no - it doesn't play nicely with everything BEM has to offer

travco avatar Dec 20 '15 18:12 travco

Thanks for the response!

For now, We've changed our internal methodology to use %parent--variation in lieu of %parent.-modifier when we need to change more than a few properties. Using &--variation { &:hover { ... } } works as expected.

Thanks for the wonderful plugin & support!

Blindmikey avatar Dec 20 '15 21:12 Blindmikey

Hey travco,

I have noticed that writing nested styles like this is producing %button into the resulting css. For example:

/* Example 1 */
%button {
    span & { ...A... }
}

input[type=submit] { @extend %button; }

results in:

span %button { ...A... }

instead of the expected result:

span input[type=submit] { ...A... }

Another weird and possibly related bug is that this

/* Example 2 */
%button {
    & { ...A... }
    &--small
    {
        span,
        a {
            ...B...
        }
    }
}
input[type=submit] { @extend %button; } /* ! notice I don't @extend %button--small; */

results in:

input[type=submit]{...A...}
%button--small a,%button--small span{...B...} /* despite not extending %button--small... */

The odd part is If I change the above by removing the span, a { ...B... } to just a single selector span { ...B... }, I get what I expect:

input[type=submit]{...A...}
/* didn't extend %button--small, so correctly, no output of %button--small is found */

OR if I keep the multi-selector span, a { ...B... } but do extend %button--small, I get the correct output of:

input[type=submit]{...A...}

input[type=submit] a,
input[type=submit] span{...B...}

And one last item is that, in example 2 above, if I remove & { ...A... } then I get this error: '%button', has not been defined, so it cannot be extended but still outputs:

%button--small a,%button--small span{...B...}

Blindmikey avatar Dec 21 '15 23:12 Blindmikey

One last note about my specific use case; for an object-oriented style of CSS, I usually create a series of elements and components that can be extended and customized were needed in an application. However the following does not produce the expected output:

/* element classes */
%e-button { ...A... }
%e-textInput { ...B... }

/* component classes */
%c-searchBar 
{
    & { ...C... }
    &_submit { @extend %e-button; ... }
    &_input { @extend %e-textInput; ... }
}

/* instance of a component ( object ) */
.App
{
    & { ...D... }
    &-search { @extend %c-searchBar; ... }
}

This would hopefully output:

.App { ...D... }
.App-search { ...C... ... }
.App-search_input { ...B... ... }
.App-search_submit { ...A... ... }

But instead currently outputs:

.App { ...D... }
.App-search { ...C... ... }
%c-searchBar_input,%e-textInput { ...B... ... }
%c-searchBar_submit,%e-button { ...A... ... }

Blindmikey avatar Dec 22 '15 05:12 Blindmikey