๊ฐœ๋ฐœ ๐Ÿพ/HTML,CSS

Node ๊ธฐ๋ฐ˜ SASS ์ž…๋ฌธํ•˜๊ธฐ

JOTOKKI 2021. 7. 1. 16:18
728x90

์˜ค๋žœ๋งŒ์— html, css, javascript๋กœ ์ฝ”๋”ฉ์„ ํ•ด์•ผ ํ•˜๋‹ค ๋ณด๋‹ˆ, ์˜ ๊ธฐ์กด์ฒ˜๋Ÿผ ํ•˜๊ธฐ์—๋Š” ๊ท€์ฐจ๋‹ˆ์ฆ˜์ด ์ƒ๊ฒจ๋ฒ„๋ ธ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜…

๊ทธ๋™์•ˆ์€ ๋”ฑํžˆ ๊ด€์‹ฌ ๊ฐ–์„ ๋งŒํ•œ ์ผ์€ ์—†์—ˆ์œผ๋‚˜ ๊ท€์ฐฎ์€ ๊ฑด ๋„ˆ๋ฌด ์‹ซ์œผ๋‹ˆ ์—†๋˜ ๊ด€์‹ฌ์ด ์ƒ๊ธฐ๊ฒŒ ๋˜๋ฉด์„œ ์ด๋ฒˆ ๊ธฐํšŒ์— ์ž…๋ฌธํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

 

๊ณต์‹๋ฌธ์„œ๋ฅผ ๋ณด๊ณ  ํ•˜๋‚˜์”ฉ ๋”ฐ๋ผํ•˜๊ฑฐ๋‚˜ ๊ฐ•์˜๋ฅผ ๋ณด๊ณ  ๊ณต๋ถ€ํ•ด๋„ ์ข‹์ง€๋งŒ,

์ „๋ฐ˜์ ์œผ๋กœ ํ•œ ๋ฒˆ ์งง๊ฒŒ ๊ฒ‰ํ•ฅ๊ธฐ ์‹์œผ๋กœ ์ž‘์„ฑํ•ด๋ณด๊ณ  ๊ฐ•์˜๋ฅผ ๋“ค์œผ๋ฉด ์ดํ•ดํ•˜๋Š”๋ฐ ์ข€ ๋” ๋„์›€์ด ๋˜์ง€ ์•Š์„๊นŒ ์‹ถ์Šต๋‹ˆ๋‹ค. 

 

์ฐธ์กฐ: https://sass-lang.com/

1. ํ™˜๊ฒฝ์„ธํŒ…

๊ทธ๋Ÿด ๋ฆฌ ์—†๊ฒ ์ง€๋งŒ node๊ฐ€ ์—†๋‹ค๋ฉด ์„ค์น˜ 

๊ธฐ์กด ๋ฒ„์ „(node-sass, libsass)๋Š” ํ์ง€๋˜์—ˆ๋‹ค๊ณ  ํ•˜๋‹ˆ Dart Sass๋ฅผ ์‚ฌ์šฉํ•˜๋ผ๊ณ  ํ•˜๋„ค์š”. 

npm install -g sass


// ๋งŒ์•ฝ ์จ๋ณด๊ณ  ๋‹ค์‹œ ์‚ญ์ œํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด 
npm remove -g sass 

 

sass-practice๋ผ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  vscode๋ฅผ ์—ด์–ด์ค๋‹ˆ๋‹ค. 

mkdir sass-practice
cd sass-practice 
code .

 

๊ทธ๋ฆฌ๊ณ  src ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ src ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ์ƒ์„ฑํ•œ ๋’ค scss ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด๋ด…๋‹ˆ๋‹ค.

// src/style.scss
$color: red;

์ด์ œ ์ด ํŒŒ์ผ์„ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก css ํŒŒ์ผ๋กœ ๋ณ€ํ™˜์‹œ์ผœ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

๋ณ€ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

sass scss๋””๋ ‰ํ„ฐ๋ฆฌ๋ช…/cssํŒŒ์ผ๋ช…:๋””๋ ‰ํ„ฐ๋ฆฌ๋ช…/ํŒŒ์ผ๋ช… // ์ผ๊ด„๋ณ€ํ™˜
sass --watch scss๋””๋ ‰ํ„ฐ๋ฆฌ๋ช…:css๋””๋ ‰ํ„ฐ๋ฆฌ๋ช… // ์‹ค์‹œ๊ฐ„๋ณ€ํ™˜

์ด๋ ‡๊ฒŒ sass ๋’ค์— scss๊ฐ€ ์ €์žฅ๋˜์–ด์žˆ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ๋ช… : css๋กœ ๋ณ€ํ™˜๋œ ํŒŒ์ผ์ด ์ €์žฅ๋  ๋””๋ ‰ํ„ฐ๋ฆฌ๋ช…์„ ์ ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. 

--watch ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์ €์žฅํ•  ๋•Œ๋งˆ๋‹ค ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€ํ™˜๋ผ์„œ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

๋งŒ์•ฝ node๋ฅผ ํ†ตํ•ด ์„ค์ •ํ•ด์„œ ์“ฐ๊ณ  ์‹ถ๋‹ค๋ฉด package.json์—์„œ ์‹คํ–‰ ๋ช…๋ น์–ด๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ๊ฒฝ๋กœ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. 

npm init -y๋ฅผ ํ†ตํ•ด package.json ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด ์ฃผ์„ธ์š”. 

๊ทธ๋ฆฌ๊ณ  package.json ํŒŒ์ผ์„ ์—ด์–ด ์‹คํ–‰ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด ์ค๋‹ˆ๋‹ค.

{
  "name": "sass-practice",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build:sass": "sass src:dist", // ์ผ๊ด„ ๋ณ€ํ™˜ ์ถ”๊ฐ€
    "watch:sass": "sass --watch src:dist " // ์‹ค์‹œ๊ฐ„ ๋ณ€ํ™˜ ์ถ”๊ฐ€
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด์ œ ์šฐ๋ฆฌ๋Š” ์ €๋™ ์ปดํŒŒ์ผ์„ ํ•˜๊ธฐ ์œ„ํ•ด npm run watch:sass ๋ผ๋Š” ๋ช…๋ น์–ด๋งŒ ์น˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. 

 

2. ์‚ฌ์šฉํ•˜๊ธฐ

์ œ๊ฐ€ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑํ•ด๋ณธ ์ƒ˜ํ”Œ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. 

๋ณ€์ˆ˜์‚ฌ์šฉ, mixin ์‚ฌ์šฉ, extend ์‚ฌ์šฉ, for / if ๋ฌธ ์‚ฌ์šฉ

 

์ƒ˜ํ”Œํ™”๋ฉด

์šฐ์„  ๋งˆํฌ์—…๊ณผ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•ด ์ค๋‹ˆ๋‹ค. 

<div class="wrap theme1">
  <div class="inner">
    <button class="changeTheme btn">Chagen theme</button>
    <p>
    Lorem, ipsum dolor sit amet consectetur adipisicing elit. Odio quas, quos doloremque, temporibus eveniet sed explicabo, reiciendis ea assumenda quam amet vitae. Eveniet repellat ipsam adipisci, nostrum ipsum inventore totam?
    </p>
    <ul class="list">
      <li class="item">html</li>
      <li class="item">sass</li>
      <li class="item">javascript</li>
      <li class="item">react</li>
    </ul>
    <span class="message">I am message </span>
  </div>
</div>
<script>
    const btn = document.querySelector('.changeTheme');
    const wrap = document.querySelector('.wrap');
    btn.addEventListener('click', function(){
        if(wrap.classList.contains('theme1')) {
            wrap.classList.replace('theme1', 'theme2');
        } else {
            wrap.classList.replace('theme2', 'theme1');
        }
    })
</script>

์Šคํฌ๋ฆฝํŠธ๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ wrap์— theme1 ํด๋ž˜์Šค๋ช…๊ณผ theme2 ํด๋ž˜์Šค๋ช…์„ ํ† ๊ธ€ ์‹œ์ผœ์ฃผ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. 

scss์—์„œ template๋ฅผ ๋งŒ๋“ค๊ณ  ๊ฐ๊ฐ ํด๋ž˜์Šค ๋ช…์ผ ๋•Œ parameter๊ฐ’์„ ์ฃผ์–ด ๋‹ค๋ฅด๊ฒŒ ํ‘œํ˜„ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

์ด์ œ src/style.scss์—์„œ template์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. 

 

1. MIXIN

$padding: 2rem;

@mixin template($theme_name, $theme_bg, $theme_color) {
    padding: $padding;
    background: $theme_bg;
    color: $theme_color;
}

.theme1 {
    @include template("theme1", darkred, lightpink);
}

.theme2 {
    @include template("theme2", darkblue, lightblue );
}

๊ตณ์ด ์žฌ์‚ฌ์šฉ์„ฑ์ด ์—†๋Š” ๋ณ€์ˆ˜ ์„ ์–ธ์€ ์ง€์–‘ํ•˜๋Š” ๊ฒŒ ์ข‹๊ฒ ์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด mixin๋‚ด๋ถ€์—์„œ๋„ $padding์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์จ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

mixin ์„ ์–ธ์€ @mixin, ์‚ฌ์šฉ ์‹œ์—๋Š” @include๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. 

$theme_bg, $theme_color๋ฅผ ๋ณด๋ฉด mixin์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

2. extends

$msg_color: lightgreen;

{ ... }

.message {
    color: $msg_color;
    font-size: 1.2rem;
    font-weight: bold; 
    text-decoration: underline;
}

.theme1 {
    @include template("theme1", darkred, lightpink);
    .message {
        $msg_color: rgb(241, 146, 241);  // ๋ณ€์ˆ˜ ์žฌ์„ ์–ธ
        @extend .message;  // extend
        color: $msg_color; // ์žฌ์„ ์–ธ๋œ ๋ณ€์ˆ˜ ์ ์šฉ
    } 
}

$๋กœ ์„ ์–ธํ•œ ๋ณ€์ˆ˜๋ฅผ ๋ถ€๋ชจ ํด๋ž˜์Šค ๋‚ด์—์„œ ์žฌ์„  ์–ธ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. 

๋˜ํ•œ .message๋ผ๋Š” ์Šคํƒ€์ผ์„ extend๋ฅผ ํ†ตํ•ด ๊ฐ€์ ธ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋„ค์š”. 

 

3. if๋ฌธ

@mixin btn($theme_name) {
    border: 0 none; 
    padding: 4px 8px; 
    border-radius: 2px;
    cursor: pointer; 
    @if $theme_name == "theme1" {
        background: palevioletred;
        color: white;
    } @else {
        background: skyblue;
        color: darkblue;
    }
}

.theme1 {
    button {
        @include btn("theme1");
    }
    {...}
}

.theme2 {
    button {
        @include btn("theme2");
    }
    { ... }
}

๊ฐ๊ฐ ๋‹ค๋ฅธ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ์ฃผ์–ด ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์˜ ๋งค์นญ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜์—ฌ ๋‹ค๋ฅธ ์Šคํƒ€์ผ์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

ํ•จ์ˆ˜ ์„ ์–ธ ์‹œ์—๋Š” @๊ฐ€ ๋ถ™์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ return ํ•  ์ผ์ด ์žˆ๋‹ค๋ฉด @return ์ด๋ ‡๊ฒŒ ์จ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. 

 

4. for๋ฌธ

.list {
    list-style-type: none;
    padding: 0;
    @for $i from 1 through 4 {
        .item:nth-child(#{$i}):before {
            content: $i + ': ';
            margin-right: 5px;
        }
    }
}

for๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ nth-child๋ฅผ ํ†ตํ•ด ์•ž์— ์นด์šดํŠธ๋ฅผ ๋ถ™์˜€์Šต๋‹ˆ๋‹ค. 

์‹ค๋ ‰ํ„ฐ ๋‚ด๋ถ€์—์„œ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” #{ } ์•ˆ์— ์จ์ค˜์•ผ ํ•˜๋„ค์š”. 

 

ํ•ด๋‹น ๋ชฉ๋ก์„ ๋ฐฐ์—ด ๋ณ€์ˆ˜์— ๋‹ด์•„ length๊ฐ’์„ ์ฒดํฌํ•ด์„œ ์‚ฌ์šฉํ•ด๋„ ๋˜์ง€๋งŒ, ์ด๋ ‡๋“  ์ €๋ ‡๋“  ์ด๋ฏธ html์—์„œ ์„ ์–ธํ–ˆ๋˜ ๋ถ€๋ถ„์„ ํ•œ๋ฒˆ ๋” ์จ์ค˜์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ƒฅ 4๋กœ ๋ฐ•์•˜์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋” ์—ฌ๋Ÿฌ ๊ตฐ๋ฐ์—์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ํ•˜๋ฉด ๋ฐฐ์—ด์„ ์„ ์–ธํ•ด์„œ ์“ฐ๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ํŽธ๋ฆฌํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

 

5. ํŒŒ์ผ ๋ถ„๋ฆฌํ•˜๊ธฐ 

๊ธฐ์กด์— css๋‚ด์—์„œ ์™ธ๋ถ€ css๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ๋ž‘ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

@include๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. 

// src/mixin.scss

@mixin template($theme_name, $theme_bg, $theme_color) {
    ...
}

@mixin btn($theme_name) {
    ...
}
@import './mixins.scss';

{...}

์ด๋ ‡๊ฒŒ ๋ณ€์ˆ˜๋‚˜ mixin์„ ํ•œํŒŒ์ผ์— ๊ด€๋ฆฌํ•˜๋ฉด ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

 

๊ฒฐ๊ณผ

๋ฐ˜์‘ํ˜•