스타일링 정복기

개발을 처음 시작하고 html을 배우고 css를 배웠다. 배우면서 html로 구조를 잡고 css로 그 구조에 스타일을 넣어준다는게 굉장히 신선하고 재밌었다. 그러다가 1차 프로젝트를 하며 scss를 적용했고 2차프로젝트에서 styled-component로 스타일링을 하였다. 그 후 스타일드컴포넌트가 편해서 쭉 스타일드컴포넌트를 사용했는데 scss는 상대적으로 사용도 많이 해보지않았고 부족한거같아 부족함을 채우기위해 정리를 하기로 하였다.

scss

CSS는 작업이 고도화될수록 불편함도 커진다. 불필요한 선택자의 과용과 연산 기능의 한계등 프로젝트의 규모가 커질수록 아쉬운점이 커진다. 하지만 웹에서는 표준CSS만 작동한다.

CSS 전처리기(Preprocessor)

말그대로 전처리기 CSS가 동작하기 전에 사용하는 기능으로, CSS의 불편함을 확장 기능으로 상쇄할 수 있다. Sass, Less등이 있다.
CSS는 불편한점이 있기에 일단 전처리기로 작성한다. 전처리기는 CSS문법과 굉장히 유사하지만 선택자의 중첩(nesting)이나 조건문, 반복문, 다양한 단위의 연산 등 표준 CSS보다 훨씬 많은 기능을 사용해서 편리하게 작성할 수 있다. 그렇기에 전처리기를 사용하는것! 하지만 웹에서는 직접 동작하는게 아니라 이렇게 작성한 전처리기를 웹에서 동작 가능한 표준의 CSS로 컴파일한다. 작성은 전처리기로 결국 동작은 CSS 보통 전처리기 3대장으로 Less, Sass(SCSS), Stylus가 있다. Sass(scss)는 나머지 두 가지의 전처리기의 장접을 모두 가지고 있으며 2006년부터 시작하여 가장 오래된 CSS확장 언어이며 그만큼 성숙도도 높다고한다.

그렇다면 Sass SCSS 차이는??

SCSS는 Sass의 3버전에서 새롭게 등장하였고 CSS구문과 완전히 호환되도록 새로운 구문을 도입해 만든 Sass의 모든 기능을 지원하는 CSS의 상위집합(Superset)이다. 그 말은 SCSS는 CSS와 거의 같은 문법으로 Sass기능을 지원한다는 말
간단하게 눈에 보이는 차이라면 {}중괄호와 ;세미콜론의 유무

Sass

.div
  width: 100px
  height: 100px
  li
    color: blue

SCSS

.div {
  width: 100px;
  height: 100px;
  li {
    color: blue;
  }
}

Sass는 셀렉터의 유효범위를 들여쓰기로 구분하고 SCSS는 중괄호로 구분한다.
sass 와 scss가 처음에는 같은건줄 알았었는데 다른점이 분명히 있고 나는 scss를 사용했다.

SCSS의 문법들

  • 주석 SCSS의 주석은 /_ … _/ 을 사용한다.

    /*
    p {
    font-size: 20px
    }
    */
  • 중첩(Nesting) 상위 선택자의 반복을 피하고 좀 더 편리하게 복잡한 구조를 작성할 수 있다.

    .header {
    width: 100%;
    .list {
      padding: 20px;
    }
    }

    이 코드가 결국 요렇게 컴파일이 된다

    .header {
    width: 100%;
    }
    .header .list {
    padding: 20px;
    }
  • 상위 선택자 참조(Ampersand) 중첩 안에서 & 키워드는 상위(부모) 선택자를 참조하여 치환한다.

    .btn {
    position: absolute;
    &.active {
      color: red;
    }
    }
  • 중첩 벗어나기(@at-root) 중첩에서 벗어나고 싶을 때 @at-root 키워드를 사용. 중첩 안에서 생성하는데 중첩 밖에서 사용해야하는 경우에 유용하다.

    .list {
    $w: 100px;
    li {
      width: $w;
    }
    @at-root .box {
      width: $w;
    }
    }

    특정 변수를 범위 밖에서 사용할 수 없기 때문에 @at-root 키워드를 사용한다.

  • 중첩된 속성 font-, margin- 등과 같이 동일한 네임 스페이스를 가지는 속성들을 다음과 같이 사용할 수 있다.

    .box {
    font: {
      weight: bold;
      size: 10px;
    }
    margin: {
      top: 10px;
      left: 20px;
    }
    }
  • 변수 반복적으로 사용되는 값을 변수로 지정할 수 있다. 변수 이름앞에는 항상 $를 붙인다.

    $my-color: blue;
    $w: 200px;
    
    .box {
    width: $w;
    background-color: $my-color;
    }

    중첩 벗어나기에서 설명했지만 변수는 사용 가능한 유효범위를 가진다. 선언된 블록 내에서만 유효범위를 가진다.
    !global 를 사용하면 변수의 유효범위를 전역으로 설정할 수 있다.

    .box1 {
    $color: green !global;
    }
    .boxw {
    background: $color;
    }
  • !default(초기값 설정) !default 는 할당되지 않은 변수의 초기값을 설정한다. 즉 할당되어있는 변수가 있다면 변수가 기존 할당 값을 사용함.

    $my-color: red;
    
    .box {
    $my-color: blue !default;
    background: $my-color; // red
    }

    이미 존재한다면 덮어쓰기 하지 않는다는 뜻이다.

    // config.scss
    $my-color: red;
    // main.scss
    @import 'config';
    
    $my-color: blue !default;
    
    .box {
    color: $my-color; // red
    }
  • 가져오기 (import) @import 로 외부에서 가져온 sass 파일은 모두 단일 CSS출력 파일로 병합된다. 또한 가져온 파일에 정의된 모든 변수 또는 Mixins 등을 주 파일에서 사용할 수 있다.
    Sass의 @import 는 기본적으로 Sass 파일을 가져오는데, CSS @import 규칙으로 컴파일되는 몇 가지 상황이 있다.

    • 파일 확장자가 .css일 때
    • 파일 이름이 http://로 시작하는 경우
    • url()이 붙었을 경우
    • 미디어쿼리가 있는 경우

    위의 경우 CSS @import 규칙대로 컴파일 된다.

    @import 'hello.css';
    @import 'hello' screen;

    여러 파일 가져오기

    @import 'header', 'footer';

    파일 이름은 ,로 구분한다.

  • 연산 Sass는 기본적인 연산 기능을 제공한다. 어떤상황에? 레이아웃 작업 시 상황에 맞게 크기를 계산하거나 정해진 값을 나눠서 작성할 경우 유용.

    • (-) 더하기
    • (-) 빼기
    • (*) 곱하기 (하나 이상의 값이 반드시 숫자)
    • (/) 나누기 오른쪽 값이 반드시 숫자
    • (%) 나머지
    • (==) 동등
    • (!=) 부등
    • (<) 대소
    • (>) 대소
    • (<=) 대소 및 동등
    • (>=) 대소 및 동등
    • and 그리고
    • or 또는
    • not 부정
  • 숫자 일반적으로 절댓값을 나타내는 px 단위로 연산을 한다. 상대적 단위(%,em,vw)의 경우 CSS calc()로 연산해야 한다.

    width: 50% - 20px; // 단위 모순 에러
    width: calc(50% = 20px); // 가능

    나누기의 경우 font: 16px / 22px serif; 같은 경우 font-size와 line-height의 속성 분리를 위해 /를 사용하기 때문에 사용하려면 조건을 충족해야한다.

    • 값 또는 그 일부가 변수에 저장되거나 함수에 의해 반환되는 경우
    • 값이 ()로 묶여있는 경우
    • 값이 다른 산술 표현식의 일부로 사용되는 경우
    div {
    $x: 100px;
    width: $x / 2;
    heght: (100px / 2);
    font-size: 10px + 12px / 3;
    }
  • 문자 문자 연산에는 +가 사용된다. 문자 연산의 결과는 첫 번째 피연산자를 기준으로 한다. 첫 번째 피연산자에 따옴표가 붙어있다면 연산 결과도 따옴표로 묶고 첫 번쨰 피연산자에 따옴표가 없다면 결과도 없다.

    div::after {
    content: 'Hello' + World;
    flex-flow: row + '-reverse' + ' ' + wrap;
    }
    
    // Compiled to
    div::after {
    content: 'Hello World';
    flex-flow: row-reverse wrap;
    }
  • 논리 연산

    $width: 90px;
    div {
    @if not($width > 100px) {
      height: 300px;
    }
    }
    // compiled to
    div {
    hegiht: 300px;
    }
  • 재활용(Mixins) Sass의 Mixin은 스타일 시트 전체에서 재사용 할 CSS 선언 그룹을 정의하는 아주 훌륭한 기능! 약간의 믹스인으로 다양한 스타일을 만들어낼 수 있다. 선언하기(@mixin)와 포함하기(@include)

    @mixin 믹스인이름 {
    스타일;
    }
    
    @include 믹스인이름;
    
    @mixin text {
    font: {
      size: 16px;
      weight: bold;
    }
    }
    h1 {
    @include text;
    }

    믹스인은 함수처럼 인수를 가질 수 있다. 따라서 하나의 믹스인으로 다양한 결과를 만들 수 있다 확장성!!

    @mixin line($width, $height) {
    width: $width;
    height: $height;
    }
    
    .box {
    @include line(50px, 20px);
    }
  • 확장 (Extend) 특정 선택자가 다른 선택자의 모든 스타일을 가져야하는 경우 확장 기능을 사용한다.

    .btn {
    padding: 10px;
    margin: 15px;
    }
    .btn-other {
    @extend .btn;
    background: red;
    }
  • 조건문

    if (함수)

    조건의 값(true, false)에 따라 두 개의 표현식 중 하나만 반환한다. 조건값이 true면 표현식1을 false이면 표현식2를 실행

    if(조건, 표현식1, 표현식2)
    $width: 500px;
    div {
    width: if($width > 300px, $width, null);
    }

    @if (지시어)

    @if 지시어는 조건에 따른 분기 처리가 가능하며 if문과 유사하다. 같이 사용할 수 있는 지시어는 @else, if가 있다.

    @if (조건) {
    /* 참일때 실행 */
    } @else if (조건2) {
    /* 조건2가 참일때 실행 */
    } @else {
    /* 모두 거짓일때 실행 */
    }

    조건에는 논리 연산자 and, or , not이 사용가능하다.

    @if $size >= 0 and $size <= 200px {
    //
    }
  • for 반복문 @for 은 through를 사용하는 형식과 to를 사용하는 형식으로 나뉜다.

    // through
    // 종료 만큼 반복
    @for $변수 from 시작 through 종료 {
    // 내용
    }
    // to
    // 종료 직전까지 반복
    @for $변수 from 시작 to 종료 {
    // 내용
    }
    // 1부터 3번 반복
    @for $i from 1 through 3 {
    .through:nth-child(#{$i}) {
      width: 20px * $i;
    }
    }
  • @each @each는 list와 map 데이터를 반복할 떄 사용한다. for in 문과 유사

    @each $변수 In 데이터 {
    //반복내용
    }
    
    $fruits: (apple, orange, banana) .fruits {
    @each $fruit in $fruits {
      li.#{$fruit} {
        background: url('/images/#{fruit}.png');
      }
    }
    }

    헤로피님의 블로그를 참고하며 작성하였습니다. https://heropy.blog/2018/01/31/sass/


Written by@jaeyoung-son
배운것을 기록하는 공간입니다.

GitHub