-
320x100
프롤로그
시리즈의 3번째 글! 이런 분들이 읽으시면 좋아요.
- CSS를 다룰 수 있어요
- 하지만 Sass는 잘 몰라요
아무튼 Sass 시리즈
1. 시작하기 - Sass 개념, 컴파일러 설치
2. 기본 작성법 익히기 - 중첩, 참조, 변수, 보간
3. 더 편하게 CSS 다루기 - mixin, extend, 모듈화(import/use) 👈 Here!
4. 더 멋지게 활용하기 - 흐름제어, 내장 모듈, 함수이번 글에서 다루는 것:
- mixin
- extend
- 모듈화(import/use)
1) 믹스인: 찍어내기 틀
이번에는 조금 더 우리의 작업을 편하게 해줄 Sass 문법을 써봅시다!
바로 @으로 시작하는 At-Rules입니다.
기본 CSS에서도 @으로 시작하는 문법들이 몇 개 있었죠. (@font-face 또는 @counter-style, @media 등)
Sass 에서는 여기에 더해 어썸한 기능들을 제공하는 at-rules 들이 추가됩니다. 예를 들면...
- @mixin / @include : 스타일 청크(묶음)를 쉽게 재사용할 수 있습니다.
- @extend : 여러 선택자가 스타일을 상속받도록 할 수 있습니다.
- @import / @use : 다른 스타일시트에 있는 변수, 함수, 믹스인 등을 불러와 결합해서 쓸 수 있습니다.
- @function : SassScript에서 사용할 수 있는 사용자 정의 함수를 만들 수 있습니다.
- @if / @each / @for : 상황에 맞춰 CSS가 적용되도록 흐름을 제어할 수 있습니다.
(이 모든 게 공짜..!)
우선 알아볼 것은 '찍어내기 틀'인 믹스인(mixin) 입니다.
믹스인을 사용하면 여기저기 써먹을 수 있는 스타일을 정의할 수 있습니다.
사용법:
① @mixin {이름} 으로 공통으로 쓸 속성들을 묶습니다
② @include {믹스인 이름} 으로 불러와 사용합니다
③ 👍
@mixin set-color { color: #fff; background-color: yellow; } h1 { @include set-color } p { @include set-color }
반복되는 속성을 하나하나 타이핑할 필요가 없으니 좋네요!
수정할 때도 믹스인을 변경하면 알아서 바뀔 테니 유지보수 하기에도 좋습니다.
TMI
변수와 마찬가지로 믹스인 이름을 지을 때 하이픈(-)과 언더스코어(_)는 동일하게 취급됩니다.
믹스인에게 인자를 주자
믹스인은 '인자(Arguments)'를 가질 수 있습니다. 넵, 함수가 실행될 때 넘겨받는 값 맞습니다.
그렇다면 호출할 때마다 다르게 정의할 수도 있다는 뜻이죠!
속성은 동일하게 지정하지만 값은 다르게 주고 싶다면 아래처럼 인자를 달리 설정합니다.
@mixin set-color($color, $bg-color) { color: $color; background-color: $bg-color; } h1 { @include set-color(#000, #f0f0f0); } p { @include set-color(#bada77, #234510); }
모든 인자를 다 넘겨받는 대신, 일부 인자에는 기본값을 주거나 특정 인자만 따로 넘기는 것도 가능합니다.
예를 들면 이런 경우가 있겠죠.
background-image 를 여기저기에 써야 하는 상황입니다.
.logo { background-image: url('images/logo.png'); } .arrow { background-image: url('images/arrow.png'); } .photo { background-image: url('images/photo.jpg'); }
우리가 Sass를 쓰는 이유는? 귀찮으니까요 🤤
잘 보니까 중복되는 부분이 꽤 많은데 믹스인으로 처리할 수 있지 않을까요?
배경 이미지를 쓸 때 지정해야 하는 값은 1) 경로 2) 파일명 3) 파일확장자로 나눠 볼 수 있습니다.
이때 파일명은 계속 바뀌지만, 경로는 images/ 일 가능성이 높고 확장자도 .png를 쓸 확률이 높네요!
그러면 이 3가지를 인자로 만들어 믹스인에 쏙 넣습니다.
@mixin bg($name, $path: "/images/", $format: "png") { background-image: url("#{$path}#{$name}.#{$format}"); } .logo { @include bg('logo'); } .arrow { @include bg('arrow'); } .photo { @include bg('photo', $format:'jpg'); }
반복되는 부분을 확 줄이고 인자만으로 배경 이미지를 쉽게 넣을 수 있게 됐습니다! 🙌
이때 인자는 차례대로 넣어야 하기 때문에 특정 인자만 넣으려면
$format:'jpg'
처럼 콕 집어서 넣어야 합니다.또 기본값이 없는 인자는 필수값으로 취급되므로,
@include bg();
처럼 사용하면 에러가 발생합니다.그리고 값을 줄 때
#{}
보간을 사용해서 문자열 안에 변수를 집어넣은 것도 확인해보세요.이렇게 하면 이미지 폴더의 경로가 바뀌었을 때 믹스인만 수정하면 되니 수정 포인트가 줄어들죠.
만약 특정 이미지만 경로나 확장자가 바뀌면 인자만 다르게 주면 되고요. 어썸하네요!
TMI
인자의 개수를 확정할 수 없는 상태라면 ... 를 써서 임의의 인자를 전달할 수 있습니다.
ex)@mixin button ($size, $color, $args...) { }
임의 인자는 @for나 @each 같은 제어문과 함께 사용하기 좋아요. 이것도 나중에 다뤄봅니다.
믹스인의 레벨은?!
믹스인은 최상위 문(Top-Level Statements)이므로, 스타일시트의 최상위 레벨에서 사용합니다.
그렇다는 건 최상위 문이 아닌 다른 문을 믹스인 속에 포함시켜 쓸 수 있다는 거죠!
예를 들면 if 문을 써볼 수 있겠네요. 아직 @if를 배우기 전이지만 대충 감이 오실 거예요.
버튼을 어떤 곳에서는 네모나게 쓰고, 어떤 곳에서는 동그랗게 써야 하는 상황일 때,
radius 값이 인자로 넘어온 경우에만 border-radius 속성을 적용하는 예시입니다.
@mixin button($size, $radius: 0) { width: $size; height: $size; @if $radius != 0 { border-radius: $radius; } } .btn-square { @include button(100px); } .btn-circle { @include button(100px, $radius: 50%); }
See the Pen Untitled by nanalike (@nykim_) on CodePen.
믹스인에 내용 덧붙이기
@content 구문을 쓰면 @include로 불러와 쓸 때 내용을 추가로 입력할 수 있습니다.
// 1) 믹스인을 만들고... @mixin hover { &:hover { font-weight: bold; @content; } &.on { @content; } } button { // 2) 불러와 쓸 때 내용을 입력합니다. @include hover { color: red; } } /* * 출력결과: button:hover { font-weight: bold; color: red; } button.on { color: red; } */
저는 자주 쓰는 미디어쿼리 분기문을 믹스인으로 만들어 놓고, 다른 곳에서 불러와 쓰는 용도로 사용합니다.
// Break Point $tablet: 768px; $mobile: 540px; // Tablet @mixin res--tablet { @media screen and (min-width: #{$tablet}) { @content; } } // Mobile @mixin res--mobile { @media screen and (max-width: #{$mobile}) { @content; } }
.title { font-size: 16px; @include res--tablet { font-size: 14px; } @include res--mobile { font-size: 12px; } } /* * 출력: .title { font-size: 16px; } @media screen and (min-width: 768px) { .title { font-size: 14px; } } @media screen and (max-width: 540px) { .title { font-size: 12px; } } */
이렇게 하면 각 분기문에서 요소가 어떤 형태로 변할지 한눈에 보이죠! 수정하기도 쉽고요 ;)
번외: 애용하는 믹스인을 소개합니다
제가 애용하는 믹스인은 IR 기법(접근성을 위한 대체 텍스트 표시)과 말줄임 처리를 위한 속성입니다.
요 두 개는 프로젝트를 할 때마다 기본 아이템처럼 만들고 시작하는 편이에요✌️
@mixin blind { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; border: 0; white-space: nowrap; clip: rect(0, 0, 0, 0); }
@mixin ellipsis($lines: 1) { @if ($lines==1) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } @else { display: -webkit-box; overflow: hidden; text-overflow: ellipsis; -webkit-line-clamp: $lines; -webkit-box-orient: vertical; } }
2) 익스텐드: 확장
이번엔 @extend를 살펴봅니다. 이건 말그대로 '확장'으로, 기본 내용에서 뭔가를 덧붙일 때 사용해요!
사용법은 이미 존재하는 셀렉터를 @extend로 지정해주면 됩니다.
예를 들어 모든 버튼은 폰트가 굵고 보더가 있지만 클래스에 따라 보더 색상이 다른 상황입니다.
그러면 공통되는 부분(폰트굵게+보더있음)을 먼저 선언하고 @extend로 공통 스타일을 상속받습니다.
.button { font-weight: bold; border-width: 1px; } .button-confirm { @extend .button; border-color: blue; } .button-error { @extend .button; border-color: red; } /* * 출력: .button, .button-error, .button-warn { font-weight: bold; border-width: 1px; } .button-confirm { border-color: blue; } .button-error { border-color: red; } */
See the Pen Untitled by nanalike (@nykim_) on CodePen.
컴파일된 출력물을 살펴보면, 공통되는 스타일을 가진 셀렉터들끼리 묶여 있는 모습을 볼 수 있습니다.
.button-confirm과 .button-error는 거기서 "확장"된 스타일을 가지고 있고요.
믹스인과 마찬가지로 반복되는 부분을 적지 않아도 되니 엄청나게 편해지네요!
placeholder
익스텐드는 확장시킬 '기본 스타일 선언'이 필요합니다. 그렇다는 건 이 스타일은 컴파일이 됩니다.
하지만 오로지 확장만을 위해 스타일을 선언하고 싶다면 % 기호를 사용할 수 있어요.
%가 포함된 셀렉터는 오로지 @extend로 불러와 쓰기 위해 사용되며 컴파일된 CSS에 포함되지 않습니다.
See the Pen Untitled by nanalike (@nykim_) on CodePen.
@mixin vs. @extend
그럼 이쯤 들어 생기는 의문, 믹스인과 익스텐드는 꽤 비슷하게 생겼는데 뭐가 다른 걸까요?
둘 다 스타일을 캡슐화하고 재사용하기에 좋은 방식이지만 약간의 차이가 있습니다.
@mixin
- 인자를 넣을 수 있어요.
- 선택자 관리가 쉬워서 전역으로 쓰기 편해요.
- 컴파일된 CSS가 길어져요.@extend
- 연관성 있는 셀렉터들을 묶어 관리할 수 있어요.
- 미디어쿼리 등으로 셀렉터가 묶일 수 없다면 쓸 수 없어요.앞서 컴파일된 CSS를 보면 알 수 있듯이
- @mixin: 미리 정의한 속성을 복사해서 따로 적용
- @extend: 선택자를 함께 묶어 속성을 한번에 적용
한다는 차이점이 있고, 여기서의 핵심은 "얼마나 연관성이 있는가"입니다.
선택자끼리 의미론적 관계가 있다면 @extend를, 그렇지 않고 단순히 속성만 겹치는 관계라면 @mixin을 쓰는 것을 추천합니다.
앞서 저는 '말줄임 처리하는 속성'을 믹스인으로 애용한다고 했는데요, @extend로 쓰지 않는 이유는 "아무데서나" 쓰이기 때문입니다.
이걸 적용하는 게 헤더의 타이틀이 될 수도 있고, 본문이 될 수도 있고, 아니면 저기 푸터에 있는 버튼이 될 수도 있습니다.
이들 각각은 전혀 연관성이 없습니다. 그저 같은 속성을 쓸 뿐이죠. 따라서 단순 복붙인 @mixin을 사용합니다.
공통 속성을 @mixin과 @extend 로 각각 사용해본 결과입니다.
컴파일된 CSS를 보면, @extend는 전혀 상관없는 요소들끼리 묶여 있는 모습이네요.
지금은 셀렉터가 짧아서 그렇지, 클래스명이 길어지고 깊어질수록 이보다 더 지저분하게 선언될 게 분명합니다 😞
만약 CSS가 아주 길다면 수백줄은 떨어져 있는 녀석들을 불러다 같이 있으라고 세워놓은 셈이 되는 거고요.
@mixin의 경우 컴파일된 CSS가 더 길긴 하지만 큰 문제는 되지 않습니다.
대부분의 웹 서버는 반복되는 텍스트 청크를 처리하는 알고리즘으로 CSS를 압축하기 때문에 사용자가 다운로드해야하는 양을 크게 늘리지 않습니다. 즉, 컴파일된 CSS의 길이에 크게 신경쓸 필요가 없다는 뜻이죠.
@extend가 적합한 곳은 하나의 컴포넌트가 여러 스타일을 갖는 경우, 그것들을 하나의 스타일시트에서 관리할 때입니다.
예를 들면 아까처럼 버튼을 스타일링할 때 button.scss에서
@extend %button
으로 확장시켜나가는 거죠.이 경우 셀렉터끼리 연관성이 높기 때문이 꼬일 염려가 없고 관리하기도 편합니다.
See the Pen Untitled by nanalike (@nykim_) on CodePen.
저는 @extend가 제약이 많다고 여겨 별로 사용하지 않는 편이지만 그렇다고 @extend가 나쁜 것만은 아닙니다.
어떤 방법이 적합할지는 사람 바이 사람, 플젝 바이 플젝이죠!
맨 처음에도 언급했듯이 "나 편하자고 쓰는 도구"인 만큼 자기 손에 착착 붙는 방법을 택해서 쓰시면 됩니다 🙌
3) 모듈화: CSS 쪼개기
이번에는 CSS를 쪼개볼 차례입니다! 🪓✨
일반적으로 CSS는 보통 하나의 파일을 쓰지만, 그렇다고 해서 작업할 때도 한곳에 몰아 쓸 필요는 없죠.
헤더 / 메인 / 푸터 각 영역의 스타일을 분리해서 작성한다면 더 효율적으로 스타일시트를 관리할 수 있습니다.
예를 들면 _header.scss / _main.scss / _footer.scss 와 같이 쪼개놓는 거죠! 이걸 필요할 때마다 불러와 사용하면 됩니다.
특히 헤더랑 푸터는 공통 영역이므로 어디서든 불러와 쓸 수 있으면 유지보수가 편해집니다.
헤더에 수정사항이 생긴다면 _header.scss 파일만 수정하면 되니까요. 그럼 _header.scss가 컴파일 되면서 해당 파일을 사용하는 home.css, mypage.css, cart.css 등도 알아서 바뀌겠죠.
그외에 reset이나 common 같은 것들도 따로 작성해 두면 수정할 때 그 파일만 열면 되니까 편하겠네요!
이렇게 쪼개놓은 스타일시트를 '모듈'이라고 하며, 지금부터 CSS를 모듈화하는 법을 알아봅니다.
@import
방법은 간단합니다. 넵, 그냥 따로따로 작성하고 @import로 불러오면 됩니다.
사실 Sass가 아닌 일반 CSS에서도 스타일시트 내 다른 스타일시트를 임포트할 수 있어요.
/* homepage.css */ @import "common.css"; @import "header.css";
참고: https://developer.mozilla.org/ko/docs/Web/CSS/@import
하지만 위와 같이 CSS를 불러오는 건 별로 권장하지 않는 방법인데요, 이유는 브라우저가 각각의 CSS를 직렬로 불러오기 때문입니다.
따라서 common 요청하고, header 요청하고, 그 다음 CSS 요청하고... 하느라 로딩이 느려집니다.
한편, Sass에서 @import를 통해 다른 스타일시트를 불러오는 것은 조금 다릅니다.
Sass의 임포트는 "컴파일 과정에서 처리되기 때문에" 브라우저가 HTTP 요청을 여러 번 하지 않아도 되기 때문이죠!
_common.scss와 style.scss 파일을 만들고 각각 내용을 작성해 보겠습니다.
// _common.scss button {margin: 0; padding: 0; background: #fff;} // style.scss @import 'common'; .button-important {color: red;}
그리고 컴파일을 시켜보면...
_common.scss와 style.scss의 내용이 모두 들어가 있는 style.css 파일 하나만 생성됩니다.
오호라! 그럼 공통 스타일은 _common.scss에다 몰아놓고, 필요할 때마다 다른 scss 파일에서 가져와 쓰면 되겠군요!
@import를 통해 변수, 믹스인도 가져올 수 있어요. 이들만 따로 모아서 _variable.scss, _mixin.scss 등으로 분리하는 것도 좋겠네요.
언더바_는 무시합니다 (__);
여기서 알 수 있는 점은 이름 앞에 언더바(_)가 붙은 scss는 컴파일되지 않는다는 것입니다.
언더바 없이 작성한 스타일시트는 모두 독립적으로 컴파일됩니다.
따라서 앞에 언더바가 있는 파일을 보면 '이건 컴파일이 되지 않고, 가져다 쓰기 위한 모듈 파일이구나!'라고 파악할 수 있습니다.
또 하나 알 수 있는 점!
스타일시트를 불러올 때 언더바나 확장자 없이 @import 'common'; 만으로 가져왔다는 점 눈치채셨나요?
게다가 임포트할 때는 현재 파일을 기준으로 찾기 때문에 ./ 로 경로를 시작하지 않아도 됩니다 👍@use
@import는 쉽고 빠르게 다른 스타일시트를 가져올 수 있도록 해주지만,
Dart Sass를 쓰고 있다면 @import 대신 @use를 사용하는 것이 좋습니다.이유는 @import는 대상을 전역으로 불러오기 때문입니다.
변수, 믹스인, 함수 등(Sass에서는 이걸 '멤버'라고 불러요)에 전역으로 접근할 수 있기 때문에, 각 멤버가 어디서 정의되었는지 파악하기가 어렵고 이름이 충돌할 수 있다는 단점이 있습니다.
// style.scss @import 'module1'; @import 'module2'; @import 'module3'; h1 { font-weight: $font-weight; }
세 개의 스타일시트를 불러와 사용하는 style.scss 파일입니다.
변수가 있는데 내부에서 보이지 않는 걸로 보아 다른 스타일시트에서 선언된 것 같네요.
각각의 모듈 파일을 열어봤더니...
$font-weight라는 동일한 이름의 변수가 module1에도 있고 module2에도 있네요?! 게다가 3은 2를 부르고 있고... 🙀
그럼 컴파일된 결과는 어떨까요?
어디선가 변수를 받아와서 썼다는 건 알겠는데, 어디서 받아왔고 누가 덮어쓴 건지 알 수가 없습니다.
또, 주석을 보면 알 수 있지만 같은 모듈을 여러번 @import하면 전부 컴파일한다는 단점도 있습니다.
이러한 단점을 해결하기 위해 개발된 것이 @use입니다.
Sass 팀에서도 2022년 10월까지는 @import랑 헤어지겠다고 다짐한 모양이라 @use 사용을 추천합니다.(2022년 7월, @import의 사용 중단 및 제거 일정이 연기되었습니다. 80%의 사용자가 Dart Sass를 사용할 때까지 기다렸다가 사용을 중단할 예정이라고 하네요!)
따라서 이 글에서도 앞으로 @use를 사용해 모듈을 가져옵니다!
@use의 주요 특징
- 항상 파일 시작부분에 쓰여야 합니다. 스타일 규칙에 포함될 수 없어요.
- 가져온 멤버는 모두 네임스페이스를 갖습니다.
- 여러번 @use 하더라도 중복해서 가져오지 않습니다.
- 언더바(_) 또는 하이픈(-)으로 시작하는 멤버는 프라이빗으로 취급하므로 가져오지 않습니다.@use도 @import와 비슷하게
@use <불러올 scss 파일>
로 작성합니다.차이점이 있다면 멤버를 사용할 때 네임스페이스를 지정해 줘야 한다는 것!
@use "module1"; @use "module2"; @use "module3"; h1 { font-weight: module1.$font-weight; }
이렇게 하면 어느 모듈에서 가져온 변수인지 한눈에 알 수 있습니다.
함수, 믹스인 등 다른 멤버들에게도 동일하게 네임스페이스를 붙이면 됩니다.
@include할 때 어느 파일의 믹스인인지 이름을 적어주세요!
@use 'mixin'; .title { @include mixin.ellipsis; }
@use를 쓰면 네임스페이스를 같이 적어야 하므로 이름을 지을 때 간단하게 짓는 게 좋습니다.
@import를 쓸 때는 충돌을 피하기 위해 최대한 구체적으로 지었던 것과 비교되죠.
@use 'me'; @use 'you'; .my-name { content: me.$name; } .your-name { content: you.$name; }
네임스페이스는 기본적으로 파일명을 가리킵니다. (URL의 마지막 요소)
하지만 난 다른 네임스페이스로 부르고 싶어! 하시는 분들은 다르게 설정할 수도 있습니다.
@use "<url>" as <namespace>
이렇게 하면 더 짧게 호출하거나 동일한 이름으로 여러 모듈을 불러오는 것도 가능합니다.@use "module1" as m; @use "module2" as mmmmm; h1 { color: mmmmm.$color; }
이것마저 귀찮다면?! 네임스페이스 부분을 * (와일드카드)로 쓰면 네임스페이스 없이 모듈을 불러올 수 있습니다.
@use "module1" as *; @use "module2" as *; h1 { color: $color; //단, 동일한 변수가 있는 경우 충돌 }
하지만 멤버 이름이 쉽게 충돌날 수 있기 때문에 주의하여 사용하세요.
대신 @import와 다르게 @use는 덮어씌우지 않고 컴파일 단계에서 알려줍니다. 친절쓰! 👼
멤버명 앞에 언더바(_)나 하이픈(-)이 붙으면 프라이빗으로 간주하며 다른 모듈에서 불러와 쓸 수 없습니다. 일종의 지역변수죠!
@forward
@use를 사용하면 오로지 불러온 곳에서만 멤버들을 사용할 수 있습니다.
분리된 변수나 믹스인을 쓰려면 각 모듈 파일 상단에서 불러와야 한다는 뜻입니다.
네임스페이스를 명확히 한다는 목적에 맞춰 저렇게 작성하는 것이 좋지만, 그래도 좀 귀찮은 것도 사실이죠.
이럴 땐 @forward를 써봅니다.
helper/ 폴더 안에 _index.scss 라는 진입점을 만들고, 폴더 내 모듈을 _index.scss가 "전달"하도록 합니다.
원한다면 @forward 할 때 접두사를 지정할 수도 있습니다.
@forward "<url>" as <prefix>-*
로 전달하고, 사용할 때는<prefix>-
를 앞에 붙여 씁니다.네임스페이스를 지정할 거라 이름을 너무 짧게 지어서 의미를 파악하기 어렵다면 이렇게 쓸 수도 있겠죠.
이런 식으로 component/ 폴더에도 _index.scss를 만들어 컴포넌트 관련 scss 들을 한번에 전달할 수도 있겠네요!
그래서 어떻게 쪼갤까?
...는 사람 마음이죠! 저는 요런 식으로 쪼개는 취향입니다. (말이 좀...?)
scss/ ├─ base/ │ ├─ _index.scss │ ├─ _reset.scss │ ├─ _common.scss ├─ helpers/ │ ├─ _index.scss │ ├─ _mixin.scss │ ├─ _meidaQuery.scss │ ├─ _variable.scss │ ├─ _animation.scss ├─ components/ │ ├─ _index.scss │ ├─ _button.scss ├─ pages/ │ ├─ _index.scss │ ├─ _home.scss ├─ vendors/ ├─ style.scss
- base/: 리셋이나 노멀라이즈, 또는 아주 기본으로 쓰일 스타일(타이포그래피 등)
- helpers/: 직접 스타일을 적용하지 않지만 개발에 필요한 스타일(믹스인, 함수 등)
- components/: 말그대로 개별 컴포넌트!
- pages/: 말그대로 개별 페이지!
- vendors/: 외부 라이브러리 등을 사용하는 경우 필요한 스타일
- styles.scss: 컴파일할 스타일시트
에필로그
믹스인의 존재를 처음 알았을 때의 충격이란..!!
이것만 알아도 Sass의 반을 쓰는 거 아닐까요?! 하는 기능이었어요 😙
다음엔 미처 다루지 못했던 @at-rules의 함수, 흐름 제어문을 다뤄보겠습니다.
아직까진 그래도 Sass지 할 만한 기능들이라 꼭 짚어보고 싶네요!
이 시리즈의 다음 글
4. 더 멋지게 활용하기 - 흐름제어, 내장 모듈, 함수728x90'Blog > CSS' 카테고리의 다른 글
[아무튼 Sass] 4. 더 멋지게 활용하기 - 흐름제어, 내장 모듈, 함수 (6) 2022.11.05 [아무튼 Sass] 2. 기본 작성법 익히기 - 중첩, 참조, 변수, 보간 (14) 2022.04.05 [아무튼 Sass] 1. 시작하기 - Sass 개념, 컴파일러 설치 (38) 2021.07.10 SVG 아이콘 백그라운드 이미지로 활용하기 (14) 2021.04.11 스크롤 앵커링: 더보기 버튼이 이상했'었'던 이유 (overflow-anchor) (11) 2020.11.22 댓글