Skip to content

Sass 父選取器 &:組合類別名、狀態與反向嵌套

Sass 父選取器 & 的用法

巢狀 裡,& 代表 目前所在位置的完整父選取器。它與一般巢狀的差別只有一個字:空白。巢狀寫 .title 會產出 .card .title,寫 &.title 會產出 .card.title

一、接偽類與偽元素

最常見的用法,:hover:focus 這類 偽類 必須黏在選取器後面:

scss
.btn {
  color: #2965f1;

  &:hover {
    color: #1b4dc1;
  }

  &::after {
    content: "→";
  }
}
css
.btn { color: #2965f1; }
.btn:hover { color: #1b4dc1; }
.btn::after { content: "→"; }

少寫一個 & 意思就變了

:hover 直接巢狀會變成 .btn :hover,選到的是「.btn 裡面被滑鼠移過的任何元素」,完全不同的東西。

二、接修飾類別

同一個元件的不同變體:

scss
.btn {
  padding: 8px 16px;

  &.is-active {
    background: #2965f1;
  }

  &.is-disabled {
    opacity: 0.5;
  }
}
css
.btn.is-active { background: #2965f1; }
.btn.is-disabled { opacity: 0.5; }

三、串接成 BEM 類別名

& 後面接文字會直接接上去,這是 BEM 寫法的基礎:

scss
.card {
  padding: 16px;

  &__title {
    font-size: 20px;
  }

  &--featured {
    border: 2px solid #2965f1;
  }
}
css
.card { padding: 16px; }
.card__title { font-size: 20px; }
.card--featured { border: 2px solid #2965f1; }

產出的選取器都只有一層,優先權 維持在 0,1,0,同時原始碼裡 .card 相關的樣式全集中在一起,這是 & 最實用的地方。

這樣寫全域搜尋不到 .card__title

&__title 在原始碼裡不是字串 .card__title,用編輯器全域搜尋類別名會找不到。這是 BEM 串接寫法唯一的代價,取捨見 BEM 與 & 的搭配

四、反向嵌套

& 不一定要在最前面。放到後面,父選取器就變成祖先:

scss
.card {
  background: #fff;

  .theme-dark & {
    background: #1a1a1a;
  }
}
css
.card { background: #fff; }
.theme-dark .card { background: #1a1a1a; }

這個寫法讓「外層條件影響內層元件」的樣式,可以寫在元件自己的檔案裡,不必散到主題檔去。常見於深色模式、[dir="rtl"].no-js 這類全域旗標。

五、一行裡出現多次

& 可以重複使用:

scss
.item {
  & + & {
    margin-top: 8px;
  }
}
css
.item + .item {
  margin-top: 8px;
}

「除了第一個以外都加上間距」的經典寫法。

六、搭配插值

#{&} 取得父選取器的字串形式:

scss
.card {
  @at-root #{&}__footer {
    padding-top: 12px;
  }
}

也常拿來除錯,確認目前巢狀到哪:

scss
.a .b {
  @debug #{&}; // .a .b
}

插值@at-root 有各自的細節。

兩個限制

一、父選取器是串列時不能串接文字。

scss
.a, .b {
  &__title { color: red; } // ❌ 編譯錯誤
}

& 這時代表 .a, .b 兩條,接上 __title 會產生無效的選取器。

二、元素選取器不能串接文字。

scss
h1 {
  &-sub { color: red; } // ❌ h1-sub 不是有效選取器
}

遇到限制就改用插值

真的需要組出複雜選取器時,#{&} 搭配字串處理通常繞得過去,但先想想是不是命名該調整了。

常見問題

& 和直接巢狀寫選取器差在哪?

巢狀寫選取器會在父子之間補一個空白,變成 後代選取器& 則是直接接在父選取器後面,中間沒有空白。所以 :hover、修飾類別、BEM 的元素名這類要黏在一起的寫法都必須用 &

& 可以放在選取器中間嗎?

可以放在任何位置。寫成 .dark & 就變成反向嵌套,產出 .dark .card 這種祖先在前的選取器,適合處理外層主題類別控制內層元件的情境。

為什麼 &-title 這種寫法會出錯?

多數情況它是合法的,出錯是因為父選取器不是單純的類別名,例如父層是 .a, .b 這種選取器串列,或是 h1 這種元素選取器接上文字後變成無效選取器。這時 Sass 會直接報錯。

& 可以放進插值裡使用嗎?

可以,寫成 #{&} 就會取得目前父選取器的字串,常用來組合更複雜的選取器,或在 @debug 時確認目前的巢狀位置。它得到的是選取器串列,不是單純字串。

延伸閱讀