SCSS @extend

admin發表於2019-04-30

假如頁面中,有兩個報錯功能,一個是普通錯誤,一個是嚴重錯誤。

這樣我們可以定義兩個class樣式類,.error和.seriousError。

程式碼如下:

[CSS] 純文字檢視 複製程式碼
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  border-width: 3px;
}

嚴重錯誤具有普通錯誤的樣式特點,那麼在html中可以如此規定:

[HTML] 純文字檢視 複製程式碼
<div class="error seriousError">螞蟻部落警告</div>

但上面方式一個缺點是,每次定義嚴重錯誤樣式,都要記得一起使用普通錯誤樣式。

使用@extend可以解決上述問題,程式碼例項如下:

[Scss] 純文字檢視 複製程式碼
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}

編譯後的css程式碼如下:

[CSS] 純文字檢視 複製程式碼
.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; 
}
.seriousError {
  border-width: 3px; 
}

這樣的話,html標籤只需要如下設定即可:

[HTML] 純文字檢視 複製程式碼
<div class="seriousError">螞蟻部落警告</div>

@extend繼承它後面選擇器的樣式,但並不是簡單的將樣式插入繼承者中,而是智慧的進行了合併。

@extend如何工作:

它通過將繼承的選擇器,插入到被繼承選擇器所在的位置,然後在進行一些選擇器的合併操作。

看如下程式碼例項:

[Scss] 純文字檢視 複製程式碼
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.error.intrusion {
  background-image: url("/image/hacked.png");
}
.seriousError {
  @extend .error;
  border-width: 3px;
}

編譯成css程式碼如下:

[CSS] 純文字檢視 複製程式碼
.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; 
}
.error.intrusion, .intrusion.seriousError {
  background-image: url("/image/hacked.png"); 
}
.seriousError {
  border-width: 3px; 
}

一次性繼承多個選擇器:

我們可以一次性繼承多個選擇器,程式碼如下:

[Scss] 純文字檢視 複製程式碼
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.attention {
  font-size: 3em;
  background-color: #ff0;
}
.seriousError {
  @extend .error;
  @extend .attention;
  border-width: 3px;
}

編譯成css程式碼如下:

[CSS] 純文字檢視 複製程式碼
.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; 
}
.attention, .seriousError {
  font-size: 3em;
  background-color: #ff0; 
}
.seriousError {
  border-width: 3px; 
}

繼承鏈:

程式碼例項如下:

[Scss] 純文字檢視 複製程式碼
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
.criticalError {
  @extend .seriousError;
  position: fixed;
  top: 10%;
  bottom: 10%;
  left: 10%;
  right: 10%;
}

seriousError繼承.error。

如果criticalError再繼承seriousError,那麼criticalError就兼具error和seriousError的樣式。

選擇器序列:

選擇器序列,比如.foo .bar 或 .foo + .bar,目前還不能作為擴充套件。

但是,選擇器序列本身可以使用@extend。

[Scss] 純文字檢視 複製程式碼
#fake-links .link {
  @extend a;
}
 
a {
  color: blue;
  &:hover {
    text-decoration: underline;
  }
}

上面的程式碼會被便以為如下css程式碼:

[CSS] 純文字檢視 複製程式碼
a, #fake-links .link {
  color: blue;
}
a:hover, #fake-links .link:hover {
  text-decoration: underline; 
}

合併選擇器序列:

[Scss] 純文字檢視 複製程式碼
#admin .tabbar a {
  font-weight: bold;
}
#admin .overview .fakelink {
  @extend a;
}

按照全排列的方式,生成可能選擇器組合的數目也許很龐大,scss只會生成最可能的選擇器組合。

編譯生成css程式碼如下:

[CSS] 純文字檢視 複製程式碼
#admin .tabbar a, 
#admin .tabbar .overview .fakelink, 
#admin .overview .tabbar .fakelink {
  font-weight: bold; 
}

下面就對上面的程式碼進行一下分析:

由於它們具有共同的祖輩#admin選擇器,所以將其放在所有選擇器的開頭毫無疑問。

將.fakelink選擇器插入到被繼承的a選擇器位置。

但是我們無法判斷.tabbar和.overview誰包含誰,所以兩者就相互包含一下。

如果不希望被繼承的選擇器也會被編譯生成,可以參閱scss %佔位符一章節。

當兩個選擇器序列合併時,如果沒有包含相同的選擇器,將生成兩個新選擇器:

第一列出現在第二列之前,或者第二列出現在第一列之前。

看如下程式碼例項:

[Scss] 純文字檢視 複製程式碼
#admin .tabbar a {
  font-weight: bold;
}
#demo .overview .fakelink {
  @extend a;
}

上面的程式碼編譯成CSS程式碼如下:

[CSS] 純文字檢視 複製程式碼
#admin .tabbar #demo .overview .fakelink,
#demo .overview #admin .tabbar .fakelink {
  font-weight: bold; 
}

指令中的@extend:

在指令中使用 @extend 時(比如在@media 中)存在一些限制:Sass 不可以將 @media 層外的 CSS 規則擴充套件給指令層內的 CSS,這樣會生成大量的無用程式碼。意思是說,如果在 @media (或者其他 CSS 指令)中使用@extend,必須擴充套件給相同指令層中的選擇器。

下面的例子是可行的:

[Scss] 純文字檢視 複製程式碼
@media print {
  .error {
    border: 1px #f00;
    background-color: #fdd;
  }
  .seriousError {
    @extend .error;
    border-width: 3px;
  }
}

但是下面的例子會報錯,程式碼如下:

[CSS] 純文字檢視 複製程式碼
.error {
  border: 1px #f00;
  background-color: #fdd;
}
 
@media print {
  .seriousError {
    @extend .error;
    border-width: 3px;
  }
}

非常簡單,不再多做介紹。