Web/HTML&CSS

[SCSS] 02. Style Rules

  • -
반응형

이번 포스트에서는 Scss에서 style을 작성하는 규칙인 Style Rule에 대해서 살펴보자.

 

기본 작성법

 

그냥 쓰려면 scss나 css나 동일

scss의 특별한 기능을 사용하지 않을꺼라면 scss나 css의 사용법은 동일하다.

// scss

.button {
  padding: 3px 10acpx;
  font-size: 12px;
}
// css

.button {
  padding: 3px 10acpx;
  font-size: 12px;
}

앞으로 코드를 비교할 때 왼쪽 블록은 scss, 오른쪽 블록은 css임을 밝혀둔다.

 

삶을 윤택하게 해주는 nesting

scss의 진가는 선택자의 중첩 기능에서부터 발휘된다. 일반적인 css의 선택자는 재사용이나 계층적인 구조화가 어렵다. 예를 들어 nav ul, nav>li, nav~a 등을 나타낼 때 선택자들의 시작이 nav로 모두 같음에도 불구하고 매번 따로 작성해야 했다. 

하지만 scss에서는 산택자를 계층적으로 사용해서 조상-자손의 관계를 표현할 수 있다.

nav {
    padding: 10px;
    
    // 기본은 자손 선택자로 연결
    ul {
        list-style: none;
    }

    >li {
        display: inline-block;
    }

    ~a {
        display: block;
    }
}
nav {
  padding: 10px;
}

nav ul {
  list-style: none;
}

nav > li {
  display: inline-block;
}

nav ~ a {
  display: block;
}

한눈에 봐도 코드가 깔끔하고 관계의 추적이 용이해보인다. 나만 그러는건 아니겠지..

기본적으로 nav를 선택자로한 스타일이 잘 적용된 것을 볼 수 있고 nav ul, nav>li, nav~a 가 잘 생성된 것을 확인할 수 있다.

 

combinator( , >, ~, + 등) 의 위치는 외부, 내부 모두 가능

선택자를 중첩할 때 combinator의 위치는 외부와 내부 모두 가능하기 때문에 구성할 선택자에 따라 편하게 작성할 수 있다.

div> {
    ul {
        list-style-type: none;
    }

    a {
        font-size: 2em;
    }
}

div {
    >p {
        border-top: 1px solid gray;
    }

    div {
        border-top: 1px solid red;
    }
}
div > ul {
  list-style-type: none;
}

div > a {
  font-size: 2em;
}

div > p {
  border-top: 1px solid gray;
}

div div {
  border-top: 1px solid red;
}

위 예에서 첫번째 블록은 "div>" 를 상위 선택자로 해서 중첩하고 있도 두 번째 블록은 "div"를 상위 선택자로 사용하는 형태이다.

 

selector 목록의 중첩

comma(,)를 이용해서 선택자의 목록을 사용하는 경우에도 nesting을 잘 동작한다. 하지만 헷갈리니까 확인하고 넘어가자.

.alert,.warning {
  ul,  p {
    margin-right: 0;
  }
}
.alert ul, .alert p, .warning ul,.warning p {
  margin-right: 0;
}

좌측의 선택자가 사용된 형태를 보면 외부 선택자로 .alert과 .warning의 목록이 사용되고 있고 내부에 다시 ul과 p의 목록이 중첩되어있다. 이 경우는 마치 2중 반복문이 적용되는 것 처럼 우측과 같이 4개의 선택자 목록에 적용된다.

 

속성의 선언

 

변수의 선언과 사용

css에서는 변수의 개념이 없기 때문에 중복되는 내용이 있을 때 계속해서 값을 써주는 수밖에 없었다. 일괄적으로 변경하려면? 당연히 모든 선언을 쫒아다니며 수정해줘야 한다. 하지만 scss에서는 변수를 사용할 수 있게 되었다! 변수를 선언할 때에는 $를 사용한다.

.circle {
    $size: 100px; // 변수의 선언
    width: $size; // 변수의 사용 
    border-radius: $size * 0.5;
}
.circle {
  width: 100px;
  border-radius: 50px;
}

$size로 설정된 100px이 width와 border-radius에서 사용되고 있어 나중에 변경이 필요할 때 한 번만 변경하면 처리가 가능하다. 선언된 변수는 컴파일된 css에는 당연히 보이지 않는다.

 

보간법(interpolation)

이 변수를 이용해서는 속성을 구성할 수 있는 보간법 즉 interpolation을 적용할 수 있다. 이때는 #을 사용한다.

.rect {
    $size: 100px; // 변수의 선언
    $위: top;
    margin-#{$위}: $size; // 보간법
    padding-#{$위}: $size;
    border-radius: $size * 0.5;
}
.rect {
  margin-top: 100px;
  padding-top: 100px;
  border-radius: 50px;
}

컴파일된 css에서는 margin-top과 margin-top 처럼 #{$위}의 내용이 top으로 치환 된 것을 볼 수 있다. 역시 변경이 필요하다면 $위의 값을 변경하면 된다.

 

속성의 중첩

앞서 선택자의 중첩에 대해서 살펴봤었는데 선택자와 마찬가지로 속성도 중첩될 수 있다. 많은 속성에는 prefix가 있는데 scss에서는 이 prefix를 마치 namespace 처럼 사용해서 중첩할 수 있다. 예를 들어 font-size, font-family 처럼 동일한 prefix로 시작하는 속성들을 여러개 설정해야 한다면 매우 유용하다.

.enlarge {
    font: {
        size: 2em;
        weight: bolder;
    }

    margin: auto {
        bottom: 10px;
        top: 2px;
    }
}
.enlarge {
  font-size: 2em;
  font-weight: bolder;
  
  margin: auto;
  margin-bottom: 10px;
  margin-top: 2px;
}

 

상황에 따른 속성 적용

어떤 경우에는 상황(변수 값)에 따라서 속성의 값을 달리 하거나 또는 설정하지 말아야 할 경우도 있다. 이때는 if 같은 함수를 이용할 수 있다.

// 전역 변수 선언
$rounded: false;

.button {
    border: 1px solid black;
    border-radius: if($rounded, 5px, 1px);
}
.button {
  border: 1px solid black;
  border-radius: 1px;
}

여기서는 $rounded를 전역 레벨로 선언하고 있다. 현재는 할당된 값이 false이기 때문에 border-radius는 1px가 설정된다. 만약 $rounded가 true가 되면 당연히 border-radius는 5px이 설정된다. 또는 null을 할당하면 선언 자체를 없애버리기도 한다.

 

외부 선택자 참조 &

 

외부 선택자 참조 &

선택자를 중첩해서 사용하는데 중첩의 대상이 가상 선택자라면 한가지 고민이 필요하다. 단순히 하위 선택자를 사용하면 자손의 관계가 자동으로 추가되어버리기 때문이다. 따라서 이때는 외부 선택자에 대한 참조가 필요한데 &를 사용할 수 있다.

div {
    // 자손 선택자 적용: div의 자손 중 :hover
    :hover {
        color: blue;
    }

    // 조상 선택자 활용: div 중 hover
    &:hover {
        color: red;
    }

    // 파라미터로 전달 가능
    :not(&) {
        color: green;
    }
}
div :hover {
  color: blue;
}

div:hover {
  color: red;
}

:not(div) {
  color: green;
}

 

전체적으로 div를 외부 선택자로 하고 내부에 여러가지 선택자들이 중첩되어있다. 첫번째 경우는 div :hover처럼 자손 선택자로 분리되어버린 것을 확인할 수 있다. 하지만 두번째의 경우는 div:hover로 div에서 hover가 발생했을 때로 처리된다. 이처럼 외부 선택자 참조시 &를 사용할 수 있다. 

마지막 형태처럼 파라미터로 외부 선택자를 전달할 수도 있는데 이때는 외부 선택자와의 결합은 발생하지 않는다.

 

placeholder selector %

 

placeholder selector %

sass에서는 새로운 종류의 선택자가 추가되었는데 %를 기호로 하는 placeholder 선택자이다. 이 녀석은 재밋는 점이 자체적으로 보이지 않으며 심지어는 css에 포함되지도 않는다.

.li:hover, %strong {
    color: red;
}

%strong:hover {
    color: red;
}
.li:hover {
  color: red;
}

위의 예는 %strong 처럼 뭔가 선택자가 선언되었고 심지어는 %strong:hover처럼 가상선택자를 이용해서 확장도 하고 있다. 하지만  sass를 컴파일한 결과에는 strong에 대한 내용이 존재하지 않는다. 그럼 %는 왜 사용하는가? % 선택자는 @extend에 의해 재사용하기 위해 사용된다. (마치 자바의 abstract class와 유사하다. 자체적으로는 사용되지 않는 상속 전용의 클래스.)

%base-box {
    box-sizing: border-box;
    display: flex;

    &:hover {
        color: white;
    }
}

.action-box {
    @extend %base-box;
    color:green;
}

.reset-box {
    @extend %base-box;
    color:gray;
}
.reset-box, .action-box {
  box-sizing: border-box;
  display: flex;
}
.reset-box:hover, .action-box:hover {
  color: white;
}

.action-box {
  color: green;
}

.reset-box {
  color: gray;
}

여기서는 base-box라는 placeholder 선택자를 선언하고 .action-box와 .reset-box에서 @extend를 통해서 사용하고 있는 것을 볼 수 있다.

컴파일된 결과를 살펴보면 상당히 놀라운점이 있는데 동일한 속성을 가지는 스타일 끼리 헤처모여하고 있다는 점이다. 단순히 컴파일만 하지 않고 코드 정리까지 깔끔하게 되니 인정! (모든 스타일을 저렇게 정리해주지는 않는다 ㅎ)
반응형

'Web > HTML&CSS' 카테고리의 다른 글

[SCSS] 04. Interpolation  (4) 2022.09.17
[SCSS] 03. variable  (1) 2022.09.15
[SCSS] 01. SCSS 개요  (0) 2022.09.13
[CSS]height 100% vs 100vh  (1) 2022.09.05
display:flex  (0) 2020.09.10
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.