[태그:] Sass

  • SCSS MAP.SET() 에러

    아~~~ 별거 아닌 거 가지고 시간 낭비했네요.
    API 문서에도 제대로 설명이 안되어 있어서… ㅠㅠ

    @use "sass:map";
    $fonts:(
        font-size: 1.3rem,
        line-height: 1.8rem
    );
    map.set($fonts, color, #ccc);

    위와 같이 map.set()을 사용하면 이런 에러가 발생합니다.

    Error: expected "{".

    map.set()은 새로운 맵을 리턴하기 때문에 할당을 해주지 않아서 문법오류가 발생하는 것입니다.
    아래와 같이 변수에 재 할당을 해주면 오류가 해결됩니다.

    @use "sass:map";
    $fonts:(
        font-size: 1.3rem,
        line-height: 1.8rem
    );
    $fonts: map.set($fonts, color, #ccc);

    뭐 어려운 것도 아니고, 이런 걸 만들라고 한건데…

    @use "sass:meta";
    @use "sass:map";
    
    $font-style:(
      10 : (font-size:1.0rem, line-height:1.6rem),
      12 : (font-size:1.2rem, line-height:1.8rem),
      14 : (font-size:1.4rem, line-height:2.2rem)
    );
    @mixin fontStyle($size, $args...){
      $map : map.get($font-style, $size);
    
      @each $k, $v in meta.keywords($args){
        $map : map.set($map, $k, $v);
      }
    
      @each $k, $v in $map{
          #{$k} : #{$v};
      }
    }
    
    .test10{
        @include fontStyle(10);
    }
    .test12{
        @include fontStyle(12);
    }
    .test12-2{
        @include fontStyle(12, $line-height: 2rem);
    }
    .test14{
        @include fontStyle(14, $line-height: 3rem, $color:#ccc, $font-weight: 700);
    }
    .test10 {
      font-size: 1rem;
      line-height: 1.6rem;
    }
    
    .test12 {
      font-size: 1.2rem;
      line-height: 1.8rem;
    }
    
    .test12-2 {
      font-size: 1.2rem;
      line-height: 2rem;
    }
    
    .test14 {
      font-size: 1.4rem;
      line-height: 3rem;
      color: #ccc;
      font-weight: 700;
    }
  • SCSS 아이콘 스프라이트

    아이콘 등을 이미지 스프라이트로 작업할 때 일일이 좌표를 지정하는 것이 불편하여 일괄로 CSS를 생성하는 코드 입니다.
    아이콘의 클래스 명을 리스트로 등록하고 아이콘의 크기와 한 행에 들어가는 아이콘의 개수를 설정하면 됩니다.
    나중에 아이콘이 추가 또는 삭제되어도 리스트에서 순서만 재조정하면 좌표를 일일이 다시 수정할 필요가 없습니다.

    @use "sass:meta";
    @use "sass:list";
    @use "sass:math";
    
    $icon-list:(
        'home',     'login', 'logout', 'profile', 'menu',
        'category', 'brand', 'search', 'more',    'empty',
        'left',     'right', 'up',     'down',    'cross',
        'prev',     'next',  'close'
    );
    $size: 25px;
    $col: 5;
    
    .my-icon{
        display: inline-block;
        width: $size;
        height: $size;
        background:url(my-icon.svg) no-repeat 0 0;
        background-size:$size * $col auto;
        @each $icon in $icon-list{
            $i: index($icon-list, $icon) -  1;
            $x: ($i % $col) * -$size;
            $y: math.floor($i / $col) * -$size;
            &.#{$icon}{background-position:#{$x $y};}
        }
    }
    
    .my-icon {
      display: inline-block;
      width: 25px;
      height: 25px;
      background: url(my-icon.svg) no-repeat 0 0;
      background-size: 125px auto;
    }
    .my-icon.home {
      background-position: 0px 0px;
    }
    .my-icon.login {
      background-position: -25px 0px;
    }
    .my-icon.logout {
      background-position: -50px 0px;
    }
    .my-icon.profile {
      background-position: -75px 0px;
    }
    .my-icon.menu {
      background-position: -100px 0px;
    }
    .my-icon.category {
      background-position: 0px -25px;
    }
    .my-icon.brand {
      background-position: -25px -25px;
    }
    .my-icon.search {
      background-position: -50px -25px;
    }
    .my-icon.more {
      background-position: -75px -25px;
    }
    .my-icon.empty {
      background-position: -100px -25px;
    }
    .my-icon.left {
      background-position: 0px -50px;
    }
    .my-icon.right {
      background-position: -25px -50px;
    }
    .my-icon.up {
      background-position: -50px -50px;
    }
    .my-icon.down {
      background-position: -75px -50px;
    }
    .my-icon.cross {
      background-position: -100px -50px;
    }
    .my-icon.prev {
      background-position: 0px -75px;
    }
    .my-icon.next {
      background-position: -25px -75px;
    }
    .my-icon.close {
      background-position: -50px -75px;
    }
  • Sass에서 다크모드 적용하기 3

    미디어 쿼리나 변수를 사용할 수 없어서 클래스로 구분을 해야 하는 경우에 사용할 수 있는 코드입니다.

    @use "sass:meta";
    @use "sass:list";
    
    $color-theme: (
        bg-color: (#fff, #333),
        txt-color: #000 #efefef,
        brd-color: #666
    );
     
    @mixin getColor($flag, $p, $n){
        @each $k, $v in $color-theme{
            @if($k == $n){
                @if(meta.type-of($v) == "list"){
                    @if($flag == dark){
                        #{$p}: #{list.nth($v, 2)};
                    }@else{
                        #{$p}: #{list.nth($v, 1)};
                    }
                }@else{
                    #{$p}: #{$v};
                }
            }
        }
    }
    
    @mixin parseList($flag, $pp...){
        $p: nth($pp, 1);
        @for $i from 1 through length($p){
            @if($i % 2 == 1){
                @include getColor($flag, #{nth($p, $i)}, #{nth($p, $i + 1)});
            }
        }
    }
    
    @mixin darkmode($path, $p...){
        @include parseList(light, $p);
        @at-root .darkmode #{$path}{
            @include parseList(dark, $p);
        }
    }
    
    .test .test2{
        margin:0 10px;
        border:1px solid;
        @include darkmode(&, color, txt-color, background-color, bg-color, border-color, brd-color);
    }
    .test .test2 {
      margin: 0 10px;
      border: 1px solid;
      color: #000;
      background-color: #fff;
      border-color: #666;
    }
    .darkmode .test .test2 {
      color: #efefef;
      background-color: #333;
      border-color: #666;
    }
  • Sass에서 다크모드 적용하기 2

    Sass에서 다크모드 적용하기 에서는 IE에 대한 고려때문에 코드가 좀 복잡해졌는데, 이제 IE를 무시해도 될만하니, 좀 더 간단한 코드로 다시 작업해 봤습니다.
    굳이 믹스인 사용하지 않고 변수만 정의해서 사용하면 됩니다.

    @use "sass:meta";
    @use "sass:list";
    
    $color-theme: (
        bg-color: (#fff, #333),
        txt-color: #333 #eee,
        brd-color: #666,
    );
     
    :root{
        @each $k, $v in $color-theme{
            @if(meta.type-of($v) == "list"){
                #{"--" + $k}: #{list.nth($v, 1)};
            }@else{
                #{"--" + $k}: #{$v};
            }
        }
    };
    
    @media (prefers-color-scheme: dark){
        :root{
            @each $k, $v in $color-theme{
                @if(meta.type-of($v) == "list"){
                    #{"--" + $k}: #{list.nth($v, 2)};
                }@else{
                    #{"--" + $k}: #{$v};
                }
            }
        }
    }
    :root {
      --bg-color: #fff;
      --txt-color: #333;
      --brd-color: #666;
    }
    
    @media (prefers-color-scheme: dark) {
      :root {
        --bg-color: #333;
        --txt-color: #eee;
        --brd-color: #666;
      }
    }
    
    html, body {
      color: var(--txt-color);
      background-color: var(--bg-color);
    }
     
    .border {
      border: 1px solid var(--brd-color);
    }
  • Sass에서 다크모드 적용하기

    점점 다크모드를 적용하는 사이트들이 늘어나고 있는데, Sass를 사용하여 다크모드를 쉽게 적용할 수 있게 코드를 만들어 봤습니다.

    우선 일반 컬러 테마와 다크모드 테마를 $light-theme와 $dark-theme 맵에 각각 선언합니다. (4-13줄)
    그리고 위의 맵을 사용해서 CSS에서 var()를 사용하기 위한 변수를 선언하고, 미디어쿼리도 적용해 줍니다. (15-25줄)
    그러면 CSS의 1-13줄과 같이 변수가 생성됩니다.

    이제 본격적으로 믹스인을 생성합니다. (28-41줄)
    기본적으로 color-theme(key: value)의 형태로 한 개 이상의 키:밸류 쌍으로 된 속성을 전달할 수 있습니다. 그러나 border나 background 등과 같이 색상 이외에 다른 속성도 같이 설정할 필요가 있는 경우에 color, prefix, suffix의 속성을 가진 맵을 사용할 수 있습니다.

    43-53줄과 같이 믹스인을 사용하면 CSS의 14-29줄에 해당하는 코드를 생성합니다.
    같은 속성이 두 개씩 만들어 지는 것은 CSS의 변수나 미디어쿼리를 지원하지 않는 구형 브라우저에서는 첫 번째 속성의 컬러를 사용하고, 지원하는 브라우저는 변수와 미디어쿼리가 적용되도록 하기 위해서 입니다.
    IE와 같은 구형 브라우저를 지원할 필요가 없다면 31, 37줄의 코드는 삭제하면 됩니다.

    @use "sass:map";
    @use "sass:meta";
    
    $light-theme: (
        bgc: #fff,
        txt: #333,
        brd: #ff6
    );
    $dark-theme: (
        bgc: #333,
        txt: #eee,
        brd: #339
    );
    
    :root{
        @each $k, $v in $light-theme{
            #{"--" + $k}: #{$v};
        }
    }
    @media (prefers-color-scheme: dark){
        :root{
            @each $k, $v in $dark-theme{
                #{"--" + $k}: #{$v};
            }
        }
    }
    
    @mixin color-theme($args...){
        @each $k, $v in meta.keywords($args){
            @if(meta.type-of($v) == "string"){
                #{$k}: map.get($light-theme, $v);
                #{$k}: #{"var(--" + $v + ")"};
            }@else if(meta.type-of($v) == "map"){
                $c: map.get($v, color);
                $p: map.get($v, prefix);
                $s: map.get($v, suffix);
                #{$k}: $p map.get($light-theme, $c) $s;
                #{$k}: $p #{"var(--" + $c + ")"} $s;
            }
        }
    }
    
    html, body{
    	@include color-theme($color: txt, $background-color: bgc);
    }
    
    .border{
    	@include color-theme($border: (prefix: 1px solid, color: brd));
    }
    
    .background{
        @include color-theme($background: (color: bgc, suffix: url(bg.jpg) no-repeat 50% 50%));
    }
    :root {
      --bgc:#fff;
      --txt:#333;
      --brd:#ff6;
    }
    
    @media (prefers-color-scheme: dark) {
      :root {
        --bgc:#333;
        --txt:#eee;
        --brd:#339;
      }
    }
    html, body {
      color: #333;
      color: var(--txt);
      background-color: #fff;
      background-color: var(--bgc);
    }
    
    .border {
      border: 1px solid #ff6;
      border: 1px solid var(--brd);
    }
    
    .background {
      background: #fff url(bg.jpg) no-repeat 50% 50%;
      background: var(--bgc) url(bg.jpg) no-repeat 50% 50%;
    }