2

Problem

I mainly use the following methods. (SASS)

.person {
    &.man {
        .head { A }
    }

    &.woman {
        .head { B }
    }

    .head { C }
}

But I want to use the following method. (SASS)

.person {
    .head {
        C

        <parent_selector.man> {
            A
        }

        <parent_selector.woman> {
            B
        }
    }
}

compiled result (CSS)

.person .head { C }
.person.man .head { A }
.person.woman .head { B }

I want to know if there is such a function. Thank you.

My result

I got the idea from @falsarella's @at-root approach. It seems a bit crude, but this is also possible. (I actually used deeper selectors than the example, so it was hard to solve with at-root and #{$} alone.)

.person {
    $person: &;

    .head {
        C

        @at-root #{$person}.man .head {
            A
        }

        @at-root #{$person}.woman .head {
            B
        }
    }
}

Or it would be more convenient and readable(If the parent selector is not a simple selector.) to use it by naming $parent and overriding the previous $parent.

When I think about it once, the current selector is named $parent, so it is confusing. It might be better to ignore '>', ':after', ... of a parent selector and just name it as $person. (or create naming conventions.)

.earth {
    $parent: &;

    .person {
        $parent: &;

        .head {
            C

            @at-root #{$parent}.man .head {
                A
            }

            @at-root #{$parent}.woman .head {
                B
            }
        }
    }
}

As a result of further Googling, postcss seems to support parent selectors I want.

left click
  • 894
  • 10
  • 21
  • 3
    No: SASS ultimately compiles to CSS, which [does not have a parent selector](https://stackoverflow.com/a/1014958/1324). – Paul Roub Dec 28 '17 at 16:12
  • 1
    @Paul Roub Thank you, but it seems that what I said is not well communicated. The parent selector in sass, not the parent selector in css. I added the compiled result. – left click Dec 28 '17 at 16:34
  • 1
    Your question was clear, and the answer is the same. SASS lets you write CSS at a higher level, but it does not give you magical selector powers that CSS lacks. – Paul Roub Dec 28 '17 at 16:35
  • @Paul Roub Okay, I got it. thanks :) – left click Dec 28 '17 at 16:38

3 Answers3

4

There's no "parent" selector in Sass, but, in your case, you can use a tricky #{&} interpolation together with @at-root, like this:

.person {
    .head {
        color: white;

        @at-root .man#{&} {
            color: blue;
        }

        @at-root .woman#{&} {
            color: pink;
        }
    }
}

Resulting in the following CSS:

.person .head {
  color: white;
}
.man.person .head {
  color: blue;
}
.woman.person .head {
  color: pink;
}
falsarella
  • 12,217
  • 9
  • 69
  • 115
3

Unfortunately, not. I think the first example that you give is the best way to achieve this. Another option might be:

  .head {
    .person & {
      color: red;
    }
    .person.man & {
      color: blue;
    }
    .person.woman & {
      color: green;
    }
  }

It will produce the same compiled result as you desire. But beware of nesting the .head class. It will trip you up.

Gleb Kostyunin
  • 3,743
  • 2
  • 19
  • 36
1

The following does not really uses a parent selector. Just uses a SASS @mixin to give same CSS output.

@mixin personHead($gender) {
    @if $gender == man {
        &.man .head{
            property: A; 
        }
    }
    @if $gender == woman {
        &.woman .head{
            property: B; 
        }
    }
    @if $gender == "" {
        .head{
            property: C; 
        }
    }
}

.person { @include personHead(man); }
.person { @include personHead(woman); }
.person { @include personHead(""); }


/* Compiled CSS Output */

.person.man .head {
    property: A;
}

.person.woman .head {
    property: B;
}

.person .head {
    property: C;
}
pixlboy
  • 1,452
  • 13
  • 30