좌측의 SCSS는 .error가 정의되어있고 내부에 &--serious의 &는 외부의 선택자를 나타내기 때문에 .error--serious가 된다. 다시 .error--serious에서는 @extend .error가 있으므로 .erroe에 선언된 style인 border와 background-color를 가지는 블록과 고유한 스타일인 border-width를 갖는 블록이 생성된다.
@extend의 신기한 점은 스타일 뿐 아니라 대상의 관계가 가지는 제약사항까지 확장한다.(말이 좀 어렵네요)
좌측의 .error는 :hover를 가지고 있다. 그리고 .error--serious는 .error를 상속받는데 단지 .error의 css style 뿐 아니라 :hover 속성을 확장한다.
선택자 확장 방식
@extend는 여러 면에서 @mixin과 비교된다. @mixin이 현재의 style 규칙에 @mixin 내용을 복사해서 붙이는 반면 @extend는 style 규칙 뿐 아니라 selector의 확장 부분까지 가져온다. 이때 모든 SCSS 내용을 다 읽고 나서 구성된 관계의 제약사항을 고려하여 확장한다.
.c {
// 아직 .b가 없지만 다 읽고 나서 처리한다.
@extend .b;
}
// .b는 .a의 자식이다.
.a>.b {
color: red;
}
.a > .b, .a > .c {
color: red;
}
SCSS를 살펴보면 .c는 @extend .b 하고 있는데 아직 .b는 등장하지 않았다. 두 번째 블록에서 .b는 .a의 자식으로 설정되어있다. .b가 존재하기 위해서는 .a가 반드시 필요한 것이다. 이런 내용을 다 읽은 후 @extend가 동작한다.
최종적으로 .c는 .b를 확장하므로 반드시 .a의 자식이어야 한다. 결과로 생성된 css에는 .a>.b와 .a>.c가 생성된다.
/* .content 자손 nav 태그 중 .sidebar가 .info를 확장하려 한다.*/.contentnav.sidebar {
@extend .info;
}
/* 아래 내용은 확장에 포함되지 않는다.
왜냐하면 nav중 sidebar가 확장하는데 아래 내용은 p 중 info이므로 상충된다.*/p.info {
background-color: #dee9fc;
}
/* nav.sidebar의 조상으로 .content가 있고 .info를 확장하다 보면 .guide도 있다.
.content와 .guide의 선후 관계를 알 수 없으므로
.content .guide nav.sidebar와 .guide .content nav.sidebar 두개가 생성된다.*/.guide.info {
border: 1px solid rgba(#000, 0.8);
border-radius: 2px;
}
/* 역시 main.content .content nav.sidebar와 .content main.content nav.sidebar가 생성될 수 있지만
어치피 .content는 main.content에 부합하므로 main.content nav.sidebar만 생성된다.*/main.content.info {
font-size: 0.8em;
}
개인적으로 이렇게 복잡하게 써야할까? 쓸수 있을까 하는 생각이 들긴 한다.
place holder selector 사용
@mixin에서와 마찬가지로 @extend에도 placeholder selector(%)를 사용할 수 있다. 이녀석은 마치 java의 abstract class 처럼 상속 전용의 선택자로 단독으로 사용되지는 못한다.