Search code examples
sasscompass-sass

Sass / Scss: Changing the order of nested psuedo selectors for :before and :hover in generated CSS?


Given the following Sass:

div.test {
    display: inline-block;
    background-color: #ffffff;
    color: #000000;
    &:before {
        & { 
            &:hover {
                border: 1px solid salmon;
            }
        }
        width: 25px;
        height: 25px;
        content: "";
    }
}

The resulting CSS compiles to:

div.test {
    display: inline-block;
    background-color: #ffffff;
    color: #000000;
}

    div.test:before {
        width: 25px;
        height: 25px;
        content: "";
    }

        div.test:before:hover {
            border: 1px solid salmon;
        }

What I am attempting to do is generate div.test:hover:before (the current output is before:hover).

NOTE: I am able to generate the expected CSS by using the following Sass:

div.test {
    display: inline-block;
    background-color: #ffffff;
    color: #000000;
    &:hover {
        &:before {
            border: 1px solid salmon;
        }
    }

    &:before {
        width: 25px;
        height: 25px;
        content: "";
    }
}

However I would like to know if it is possible using the first nested approach or some modification of it.

The goal was to avoid having to repeat &:before if there was such a way to do so using Sass syntax. I am also OK with knowing it isn't possible.


Solution

  • While initially the plan was to have '&' available in SassScript as a string that could be manipulated so that you could insert values wherever you wanted, those plans have been abandoned for 3.3 due to complication. Unfortunately you'll have to wait a while to be able to do this. At the moment '&' is immutable and just means "whatever the selector chain up to this point is".

    EDIT (2020.02.15):

    it is now technically possible to achieve this with recent versions of dart-sass:

    @use "sass:selector";
    
    @mixin unify-parent($child) {
        @at-root #{selector.unify(&, $child)} {
            @content;
        }
    }
    
    div.test {
        display: inline-block;
        background-color: #ffffff;
        color: #000000;
    
        &:before {
            width: 25px;
            height: 25px;
            content: "";
    
            @include unify-parent(":hover") {
                border: 1px solid salmon;
            }
        }
    }
    

    Sources: