Is there any (good) way to extend a class within a

2019-05-31 04:08发布

问题:

I've been working on building out some Less files to help speed up my CSS workflow, and also to help produce more efficient, cleaner CSS.

The way I see it:

  • Mixins are a great way to help speed up the workflow, but they have the drawback of potentially making the outputted CSS longer than necessary.
  • Extending classes is the ideal solution for ensuring the amount of duplicate style declarations is minimized, helping clean that up...

So, to help balance things out I wrote out a set of standard, commonly used styles, using dummy classes (they are stored in a file which is imported by reference, so the styles are only output if they get extended). I set all of my Mixins to extend these classes wherever possible, which worked great for the most part.

However, I realized my pitfall once I got to my media queries... I can't extend those classes within the media query, which would be fine normally, I would just remember not to do so.. But since the Mixins also now use my extends, I can now no longer use them inside media queries either.

I'm not willing to avoid using the Mixins inside of the media queries because of this, but I'd really love to be able to find a way to keep extending classes within them to keep my output as clean as possible.

The only idea I've thought of so far is to add an extra parameter to every Mixin to specify wether it should extend or not, but that's less than ideal.

My hope is that someone can come up with a much more clever solution, that would allow me to maintain the benefit of Mixins which extend base style classes, but also maintain easy usability, without over complicating things. Might be a tall order, but here's hoping.


In case my explanation was hard to follow, this is what I would have hoped to be able to do, but is not currently possible:

Ideal Input

// extensions.less

.block {
    display: block;
}

// mixins.less

@import (reference) "extensions";

.mixin {
    &:extend(.block);
    margin: auto;
}

// styles.less

@import "mixins";

.element1 {
    .mixin();
}
.element2 {
    .mixin();
}

@media only screen and (max-width: 768px) {

    .element3 {
        .mixin();
    }
    .element4 {
        .mixin();
    }

}

Ideal Output

// styles.css

.element1, .element2 {
    display: block;
}
.element1 {
    margin: auto;
}
.element2 {
    margin: auto;
}

@media only screen and (max-width: 768px) {

    .element3, .element4 {
        display: block;
    }
    .element3 {
        margin: auto;
    }
    .element4 {
        margin: auto;
    }

}

回答1:

In short, yes, currently it is somewhat possible but requires some additional wrapping for a top level classes:

// extensions.less

.block {
    display: block;
}

// mixins.less

@import (reference) "extensions";

.mixin() {
    &:extend(.block);
    margin: auto;
}

// styles.less

@media all { // !

    @import "mixins";

    .element1 {
        .mixin();
    }
    .element2 {
        .mixin();
    }
}

@media only screen and (max-width: 768px) {

    @import (multiple) "mixins";

    .element3 {
        .mixin();
    }

    .element4 {
        .mixin();
    }
}

.element1 and .element2 (and any other class to extend .block) have to be put into @media all because currently:

Top level extend matches everything including selectors inside nested media

So if .element1 and .element2 stay in the global scope they leak into every other @media .block declaration.


(Hmm, actually for me this "top level extend matches everything" thing looks questionable and contradicts another "extend inside a media declaration should match only selectors inside the same media declaration" rule (obviously because global scope = @media all thus they should work identically)).



标签: less