특정 클래스의 스타일을 다른 클래스에서 그대로 물려받아 사용하고 싶을 때가 있습니다. (예: 기본 버튼의 형태를 물려받고 색상만 다른 에러 버튼)
@extend 키워드를 사용하면, 다른 선택자의 규칙을 상속받을 수 있습니다. 컴파일 시 중복되는 코드를 생성하지 않고 선택자들을 그룹화(, 로 연결)하여 CSS 용량을 최적화하는 데 도움을 줍니다.
// %를 붙이면 CSS로 컴파일되지 않는 추상 클래스가 됩니다.
%message-shared {
padding: 15px;
border: 1px solid #ccc;
border-radius: 8px;
}
.msg-success {
@extend %message-shared;
background-color: #d1fae5;
}
.msg-error {
@extend %message-shared;
background-color: #fee2e2;
}
/* 컴파일된 실제 CSS (선택자가 , 로 묶인 것을 확인하세요!) */
.msg-error, .msg-success {
padding: 15px;
border: 1px solid #ccc;
border-radius: 8px;
}
.msg-success {
background-color: #d1fae5;
}
.msg-error {
background-color: #fee2e2;
}
@extend를 사용할 때 일반 클래스를 상속할 수도 있지만, 주로 플레이스홀더(%)를 사용합니다. 두 방식의 컴파일 결과는 어떻게 다를까요?
.btn-base { padding: 10px; }
.btn-red {
@extend .btn-base;
color: red;
}
/* --- 컴파일 결과 --- */
.btn-base, .btn-red { padding: 10px; }
.btn-red { color: red; }
/* .btn-base가 단독으로 쓰이지 않아도
CSS 파일에 강제로 렌더링되어 용량을 차지합니다. */
%btn-base { padding: 10px; }
.btn-red {
@extend %btn-base;
color: red;
}
/* --- 컴파일 결과 --- */
.btn-red { padding: 10px; }
.btn-red { color: red; }
/* %btn-base 본체는 컴파일시 흔적 없이 사라지고,
오직 상속받은 클래스만 남습니다. (용량 최적화) */
하나의 클래스가 여러 개의 속성을 동시에 상속받을 수도 있습니다.
%box-shadow { box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
%rounded-corner { border-radius: 12px; }
.custom-card {
@extend %box-shadow; // 여러 번 사용 가능
@extend %rounded-corner;
background-color: white;
}
중첩된(Nested) 구조 안에서 무분별하게 @extend를 사용하면, SCSS 컴파일러가 모든 가능한 경우의 수를 계산하여 콤마(,)로 묶어버립니다. 이로 인해 컴파일된 CSS 용량이 기하급수적으로 늘어나고 디버깅이 불가능해집니다.
/* 😱 아주 끔찍한 상황 예시 */
.admin-panel .btn { @extend .btn-primary; }
.user-dashboard .btn { @extend .btn-primary; }
.modal-window .action-btn { @extend .btn-primary; }
/* .btn-primary가 호버 상태(:hover) 등을 가지고 있다면?
컴파일 시 아래와 같이 무수한 선택자 조합이 탄생합니다. */
.btn-primary:hover,
.admin-panel .btn:hover,
.user-dashboard .btn:hover,
.modal-window .action-btn:hover {
background-color: darkblue;
}
/* 프로젝트 규모가 커질수록 이 콤마(,) 조합은 수십, 수백 줄로 뻥튀기됩니다! */
위에서 살펴본 선택자 폭발 부작용과 코드 순서 예측의 어려움 때문에, 최신 SCSS 가이드라인에서는 가급적 @extend의 사용을 지양하고 매개변수 활용이 가능한 @mixin을 사용할 것을 강력히 권장하고 있습니다. (레거시 코드를 읽기 위해 작동 원리만 이해해 두세요!)
실무에서는 수천 줄의 SCSS를 한 파일에 작성하지 않습니다. 변수, 믹스인, 리셋, 레이아웃, 컴포넌트 별로 파일을 쪼개서 관리합니다. 파일명 앞에 언더스코어(_)를 붙이면 독립적인 CSS 파일로 컴파일되지 않는 '부분 파일(Partial)'이 됩니다.
메인 파일인 style.scss에서 @use 키워드를 사용해 조각난 파일들을 하나로 불러와 조립합니다. (과거에는 @import를 썼지만, 이름 충돌 문제로 현재는 @use를 권장합니다.)
| 폴더명 (7-1 Pattern 예시) | 포함되는 파일 (Partials) | 역할 설명 |
|---|---|---|
| abstracts/ | _variables.scss, _mixins.scss |
실제 CSS 코드는 출력하지 않고 변수와 믹스인만 정의 |
| base/ | _reset.scss, _typography.scss |
HTML 태그 기본 스타일 및 웹 폰트 초기화 |
| components/ | _buttons.scss, _cards.scss |
재사용 가능한 UI 컴포넌트 단위의 스타일 |
| layout/ | _header.scss, _footer.scss |
사이트의 전반적인 골격과 레이아웃 스타일 |
파일명 앞에 언더스코어(_)를 붙여 부분 파일(Partial)을 만들고, 메인 파일에서 @use로 불러옵니다. 불러올 때 자동으로 네임스페이스가 생성되며, as 키워드를 사용해 네임스페이스를 원하는 대로 변경할 수 있습니다.
$primary: #4f46e5;
$font-stack: 'Helvetica Neue', sans-serif;
@mixin box-shadow {
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
// 불러올 때 확장자(.scss)와 언더스코어(_)는 생략 가능합니다.
@use 'variables' as v;
@use 'mixins' as m;
.module-test {
// 네임스페이스(v., m.)를 통해 접근하므로 이름 충돌이 절대 발생하지 않습니다!
font-family: v.$font-stack;
color: v.$primary;
@include m.box-shadow;
padding: 20px;
border-radius: 8px;
}
.module-test {
font-family: "Helvetica Neue", sans-serif;
color: #4f46e5;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
padding: 20px;
border-radius: 8px;
}
파일이 많아지면 @use를 수십 번 작성해야 해서 불편할 수 있습니다. 이럴 때 @forward를 사용하면 여러 부분 파일들을 하나의 진입점(Entry point) 파일로 묶어서 다른 곳에 일괄 내보낼 수 있습니다. (JavaScript의 export * from '...' 패턴과 유사합니다.)
/* 여러 파일을 묶어서 내보냅니다. */
@forward 'variables';
@forward 'mixins';
@forward 'functions';
/* 이제 main.scss에서는 abstracts 폴더만 한 번 @use로 불러오면
모든 변수와 믹스인을 한꺼번에 사용할 수 있습니다! */
Sass 공식 문서에 따르면 @import는 전역 스코프 오염과 중복 컴파일로 인한 성능 문제 때문에 조만간 완전히 폐기될 예정입니다. 새로 작성하는 모든 프로젝트에서는 반드시 @use를 사용해야 하며, 네임스페이스를 통해 명시적으로 변수와 믹스인에 접근해야 합니다.
버튼을 마우스로 호버했을 때 조금 더 어두운 색으로 만들고 싶다면? 포토샵을 열어 헥스 코드(Hex)를 찾을 필요가 없습니다.
SCSS는 자체적으로 수학 계산과 색상 조작을 위한 강력한 내장 함수(Built-in Functions)를 제공합니다. darken(), lighten(), rgba() 등의 함수를 활용하면 단일 메인 컬러 변수 하나만으로도 수십 가지의 파생 컬러 시스템을 자동으로 구축할 수 있습니다.
| 함수명 | 역할 | 사용 예시 |
|---|---|---|
| darken() | 주어진 색상을 특정 비율만큼 어둡게 만듭니다. | darken($primary, 10%) |
| lighten() | 주어진 색상을 특정 비율만큼 밝게 만듭니다. | lighten($primary, 20%) |
| rgba() | 헥스 색상에 투명도(Alpha)를 추가합니다. | rgba($primary, 0.5) |
<div class="btn-group">
<button class="btn-color">기본 상태</button>
<button class="btn-color hover-sim">Hover 상태 (15% 어두워짐)</button>
<button class="btn-color active-sim">Active 상태 (20% 더 어두워짐)</button>
</div>
/* SCSS 내장 함수 예시 */
/*
$theme-color: #38bdf8; // 밝은 하늘색
.btn-color {
background-color: $theme-color;
color: white;
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.2s;
&:hover {
// 기존 색상에서 15% 어둡게 만듭니다.
background-color: darken($theme-color, 15%);
}
&:active {
background-color: darken($theme-color, 25%);
}
}
// 브라우저 결과를 보여주기 위한 시뮬레이션 클래스
.hover-sim {
background-color: darken($theme-color, 15%);
}
.active-sim {
background-color: darken($theme-color, 25%);
}
*/
/* 컴파일된 실제 CSS */
.btn-group {
display: flex; gap: 10px; padding: 20px;
}
.btn-color {
background-color: #38bdf8;
color: white;
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.2s;
}
.btn-color:hover, .hover-sim {
background-color: #069cdb; /* 어두워진 색상 자동 계산 */
}
.btn-color:active, .active-sim {
background-color: #046b96; /* 더 어두워진 색상 */
}
웹 프로젝트가 커지면서 기존 CSS만으로는 코드가 수천 줄로 늘어나고 관리가 불가능해지는 문제(유지보수 지옥)가 발생했습니다.
이러한 불편함을 해소하기 위해 등장한 것이 바로 CSS 전처리기(Preprocessor)인 SCSS(Sassy CSS)입니다. SCSS는 변수, 중첩, 반복문, 함수 등 프로그래밍 언어의 특징을 CSS에 도입하여 코드를 획기적으로 줄이고 재사용성을 극대화합니다.
| 특징 | 기존 CSS | SCSS (Sassy CSS) |
|---|---|---|
| 유지보수 | 어려움 (코드 중복 심함) | 쉬움 (변수와 모듈화) |
| 구조화 | 평면적이고 반복적 | 계층적 (Nesting 지원) |
브라우저는 오직 순수 CSS만 해석할 수 있습니다. 따라서 SCSS로 작성된 코드는 반드시 컴파일(Compile) 과정을 거쳐 일반 CSS 파일로 변환되어야 합니다.
<!-- SCSS는 개발 환경에서만 작성되고, 브라우저에는 컴파일된 CSS가 적용됩니다. -->
<div class="card">
<h2>SCSS 컴파일 결과 확인</h2>
<button class="btn primary">확인</button>
<button class="btn danger">취소</button>
</div>
/* 아래 코드는 SCSS가 일반 CSS로 컴파일된 결과입니다. */
.card {
padding: 20px;
background-color: #f8f9fa;
border-radius: 8px;
}
.card h2 {
color: #333;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
font-weight: bold;
cursor: pointer;
}
.btn.primary {
background-color: #007bff;
color: white;
}
.btn.danger {
background-color: #dc3545;
color: white;
}
반응형 웹을 만들 때마다 모바일, 태블릿, 데스크탑의 픽셀(px) 중단점(Breakpoint)을 기억하고 매번 타이핑하기는 매우 고통스럽습니다.
믹스인의 특별한 지시어인 @content를 활용하면, 미디어 쿼리의 뼈대를 미리 만들어두고 그 내부에 원하는 스타일 블록을 나중에 동적으로 주입할 수 있습니다. 이를 통해 반응형 코드를 극도로 직관적이고 깔끔하게 관리할 수 있습니다.
@content는 마치 React의 {children}이나 Vue의 <slot>과 같은 역할을 합니다. 믹스인을 호출할 때 중괄호 {} 안에 작성한 CSS 코드 덩어리 전체를 @content 위치에 통째로 렌더링해 줍니다.
<div class="hero-section">
<h1>반응형 웹사이트 만들기</h1>
<p>창 크기를 줄여보세요!</p>
</div>
/* SCSS 반응형 믹스인 설계 */
/*
// 1. 브레이크포인트 변수 선언
$bp-mobile: 768px;
$bp-tablet: 1024px;
// 2. 미디어 쿼리 믹스인 생성 (@content 가 핵심!)
@mixin mobile {
@media (max-width: #{$bp-mobile}) {
@content; // mixin을 호출할 때 넘겨준 중괄호 {} 안의 내용이 이 자리에 들어갑니다.
}
}
@mixin tablet {
@media (max-width: #{$bp-tablet}) {
@content;
}
}
// 3. 실제 적용
.hero-section {
padding: 100px 50px;
background-color: #f1f5f9;
text-align: center;
font-size: 24px;
// 관련 코드를 분산시키지 않고 이 블록 안에서 바로 반응형 처리!
@include tablet {
padding: 80px 30px;
font-size: 20px;
}
@include mobile {
padding: 50px 15px;
background-color: #cbd5e1; // 모바일에서는 배경색도 변경
font-size: 16px;
}
}
*/
/* 컴파일된 실제 CSS */
.hero-section {
padding: 100px 50px;
background-color: #f1f5f9;
text-align: center;
font-size: 24px;
}
@media (max-width: 1024px) {
.hero-section {
padding: 80px 30px;
font-size: 20px;
}
}
@media (max-width: 768px) {
.hero-section {
padding: 50px 15px;
background-color: #cbd5e1;
font-size: 16px;
}
}
BEM은 .card__title--active 처럼 클래스명으로 부모-자식 관계와 상태를 명확히 나타내는 CSS 네이밍 컨벤션입니다. 하지만 순수 CSS에서는 클래스명이 너무 길어져 타이핑하기 번거롭습니다.
SCSS의 부모 참조 연산자 &를 BEM과 결합하면, 중첩(Nesting)의 깊이를 1단계로 유지하면서도 BEM 클래스명을 자동으로 생성할 수 있어 코드의 가독성과 유지보수성이 극대화됩니다.
| 구성요소 | 구분자 | 설명 및 예시 |
|---|---|---|
| Block (블록) | 없음 | 독립적으로 의미를 가지는 최상위 컴포넌트 (예: .card, .nav) |
| Element (요소) | __ (언더스코어 2개) | 블록 내부에 종속된 하위 요소 (예: .card__title, .nav__item) |
| Modifier (상태) | -- (하이픈 2개) | 블록이나 요소의 모양/상태 변경 (예: .card--dark, .nav__item--active) |
& 연산자를 사용하여 부모 선택자를 참조하면, 컴파일 시 부모 이름이 문자열로 치환되며 BEM 클래스명이 완성됩니다.
<!-- BEM 방식으로 작성된 제품 카드 -->
<article class="product-card">
<div class="product-card__content">
<h2 class="product-card__title">최신형 노트북</h2>
<p class="product-card__price product-card__price--discount">1,200,000원</p>
</div>
<button class="product-card__button">구매하기</button>
</article>
/* SCSS 작성법 (& 기호가 .product-card 로 치환됨) */
.product-card {
border: 1px solid #ddd;
border-radius: 8px;
max-width: 300px;
/* Element */
&__content {
padding: 20px;
}
&__title {
font-size: 1.25rem;
font-weight: bold;
}
&__price {
color: #333;
/* Modifier: 상태나 변형은 &-- 로 연결 */
&--discount {
color: #ef4444;
font-weight: bold;
text-decoration: underline;
}
}
/* 가상 클래스(Pseudo-class)도 &로 연결 */
&__button {
background: #3b82f6;
color: white;
&:hover {
background: #2563eb;
}
}
}
실무에서는 &__나 &--를 매번 타이핑하는 대신, Mixin과 문자열 보간(Interpolation, #{})을 활용해 BEM 구조를 함수처럼 강제하는 아키텍처를 많이 사용합니다. 이 방법을 사용하면 팀원들이 실수로 잘못된 BEM 컨벤션을 사용하는 것을 원천 차단할 수 있습니다.
/* BEM 제어용 믹스인 정의 */
@mixin e($element) {
&__#{$element} {
@content;
}
}
@mixin m($modifier) {
&--#{$modifier} {
@content;
}
}
/* 믹스인 활용 예시 */
.product-card {
/* @include e('content')는 결국 &__content 와 동일합니다. */
@include e('content') {
padding: 20px;
}
@include e('price') {
color: #333;
@include m('discount') {
color: #ef4444;
}
}
}
초보자들이 가장 많이 하는 실수는 HTML 구조와 똑같이 4단계, 5단계 이상 중첩하는 것입니다. (예: .nav { ul { li { a { span { ... } } } } }) 이렇게 하면 컴파일된 CSS의 구체성(Specificity)이 불필요하게 높아져 스타일 덮어쓰기가 매우 힘들어집니다. 중첩은 최대 3단계를 넘지 않는 것이 좋으며, BEM을 사용하면 1단계로 평탄화할 수 있습니다.
CSS는 프로그래밍 언어가 아니기 때문에 조건에 따라 스타일을 바꾸거나 수십 개의 클래스를 반복해서 생성하는 것이 불가능했습니다.
SCSS는 프로그래밍 언어의 제어문(Control Flow)을 완벽하게 지원합니다. @if로 다크모드 여부를 판별하고, @for나 @each 반복문을 통해 .mt-1부터 .mt-10까지의 유틸리티 클래스를 단 3줄의 코드로 자동으로 생성해낼 수 있습니다.
| 제어문 | 자바스크립트 비교 | 사용 목적 |
|---|---|---|
| @if / @else | if () {} else {} |
테마(Light/Dark)나 조건에 따라 다른 스타일 분기 |
| @for | for (let i=1; i<=10; i++) |
1부터 N까지 순차적으로 증가하며 클래스 생성 (예: 그리드 시스템) |
| @each | array.forEach() |
컬러 리스트나 아이콘 목록 등 배열 데이터를 순회하며 생성 |
<!-- 생성된 유틸리티 클래스를 HTML에서 바로 사용 -->
<div class="mb-3 text-primary">마진 바텀 24px, 프라이머리 색상입니다.</div>
<div class="p-5 text-danger">패딩 40px, 위험 색상입니다.</div>
/* SCSS @for 및 @each 반복문 예시 */
/*
// 1. @for: 숫자를 반복하여 Margin, Padding 클래스 생성
// $i가 1부터 5까지 반복됩니다.
@for $i from 1 through 5 {
.mt-#{$i} { margin-top: #{$i * 8}px; }
.mb-#{$i} { margin-bottom: #{$i * 8}px; }
.p-#{$i} { padding: #{$i * 8}px; }
}
// 2. @each: 맵(Map, 자바스크립트의 객체와 유사) 순회하며 색상 클래스 생성
$theme-colors: (
"primary": #0d6efd,
"success": #198754,
"danger": #dc3545
);
@each $name, $color in $theme-colors {
// $name은 키(primary 등), $color는 값(#0d6efd 등)
.text-#{$name} {
color: $color;
}
.bg-#{$name} {
background-color: $color;
}
}
*/
/* 컴파일된 실제 CSS (자동으로 대량 생성됨!) */
.mt-1 { margin-top: 8px; }
.mb-1 { margin-bottom: 8px; }
.p-1 { padding: 8px; }
.mt-2 { margin-top: 16px; }
.mb-2 { margin-bottom: 16px; }
.p-2 { padding: 16px; }
/* ... (3, 4 생략) ... */
.mt-5 { margin-top: 40px; }
.mb-5 { margin-bottom: 40px; }
.p-5 { padding: 40px; }
.text-primary { color: #0d6efd; }
.bg-primary { background-color: #0d6efd; }
.text-success { color: #198754; }
.bg-success { background-color: #198754; }
.text-danger { color: #dc3545; }
.bg-danger { background-color: #dc3545; }
믹스인(@mixin)이 CSS 스타일 블록 전체를 반환한다면, 함수(@function)는 계산된 단일 값(Value)만을 반환하는 도구입니다.
픽셀(px) 단위를 상대 단위인 리단위(rem)로 변환해주는 계산식이나, 특정 공식에 따른 복잡한 애니메이션 타이밍 값을 구할 때 @function을 정의하여 사용하면 코드가 훨씬 깨끗해지고 휴먼 에러를 방지할 수 있습니다.
- @mixin: display: flex; justify-content: center; 와 같이 CSS 속성과 값의 집합을 출력할 때 사용 (반드시 @include로 호출)
- @function: 1.5rem, #ff0000 과 같이 계산된 단일 값을 출력할 때 사용 (반드시 @return 포함)
<h1 class="main-title">rem 단위 자동 변환</h1>
<p class="desc-text">픽셀 값만 넣으면 알아서 rem으로 바꿔줍니다.</p>
/* SCSS 커스텀 함수(Function) 예시 */
/*
// 1. px을 rem으로 변환하는 함수 정의
@function rem($pxValue, $baseValue: 16) {
// 수학적 연산을 통해 계산 후 @return 으로 반환
// $pxValue를 $baseValue로 나누고 'rem' 문자를 붙임 (단위 제거 기법 사용)
// SCSS 내장 모듈인 math를 사용할 수도 있습니다.
@return ($pxValue / $baseValue) * 1rem;
}
// 2. 함수 사용하기
.main-title {
// 32px을 원할 때 직관적으로 입력!
font-size: rem(32);
margin-bottom: rem(24);
}
.desc-text {
font-size: rem(18);
line-height: rem(28);
}
*/
/* 컴파일된 실제 CSS */
.main-title {
font-size: 2rem; /* 32 / 16 = 2 */
margin-bottom: 1.5rem; /* 24 / 16 = 1.5 */
}
.desc-text {
font-size: 1.125rem; /* 18 / 16 = 1.125 */
line-height: 1.75rem; /* 28 / 16 = 1.75 */
}
웹사이트의 브랜드 컬러를 변경해야 한다고 상상해보세요. 기존 CSS에서는 #3b82f6 색상을 사용한 500군데를 모두 찾아 일일이 수정해야 합니다.
SCSS에서는 $ 기호를 사용하여 색상, 폰트 사이즈, 여백 등을 변수로 저장할 수 있습니다. 변수 값 하나만 수정하면 사이트 전체의 스타일이 한 번에 변경됩니다!
| 변수 타입 | SCSS 코드 예시 |
|---|---|
| 색상 (Colors) | $primary: #ff0000;, $bg-color: rgba(0,0,0,0.5); |
| 폰트 (Typography) | $font-stack: 'Pretendard', sans-serif;, $h1-size: 2rem; |
| 크기/단위 (Sizes) | $container-width: 1200px;, $border-radius: 8px; |
<div class="profile-card">
<h2 class="profile-name">홍길동</h2>
<p class="profile-desc">프론트엔드 개발자</p>
<button class="profile-btn">팔로우</button>
</div>
/* SCSS 작성 예시 (컴파일 후 모습) */
/*
$brand-color: #8b5cf6;
$text-color: #1f2937;
$border-radius: 12px;
*/
.profile-card {
padding: 20px;
border-radius: 12px; /* $border-radius */
border: 2px solid #8b5cf6; /* $brand-color */
text-align: center;
max-width: 300px;
}
.profile-name {
color: #8b5cf6; /* $brand-color */
margin-bottom: 5px;
}
.profile-desc {
color: #1f2937; /* $text-color */
}
.profile-btn {
background-color: #8b5cf6; /* $brand-color */
color: white;
border: none;
border-radius: 12px; /* $border-radius */
padding: 10px 20px;
margin-top: 15px;
cursor: pointer;
transition: opacity 0.2s;
}
.profile-btn:hover {
opacity: 0.8;
}
기존 CSS에서는 HTML의 계층 구조를 표현하기 위해 선택자를 매번 처음부터 길게 반복해서 적어야 했습니다.
SCSS의 Nesting(중첩)을 사용하면 HTML과 동일한 시각적 계층 구조로 CSS를 작성할 수 있습니다. 상위 선택자 안에 하위 선택자를 포함시켜 가독성을 크게 높이고 타이핑 양을 줄여줍니다. 부모 선택자를 가리키는 & 기호와 결합하면 더욱 강력해집니다.
HTML 구조와 똑같이 만든답시고 4~5단계 이상 깊게 중첩하게 되면, 컴파일된 CSS의 구체성(Specificity)이 너무 높아져 스타일을 덮어쓰기 매우 힘들어집니다. 중첩은 가급적 3단계를 넘지 않도록 작성하는 것이 모범 사례입니다.
<nav class="navigation">
<ul class="nav-list">
<li class="nav-item"><a href="#">홈</a></li>
<li class="nav-item"><a href="#">소개</a></li>
<li class="nav-item active"><a href="#">서비스</a></li>
</ul>
</nav>
/* SCSS 중첩 구조 예시 (컴파일된 CSS) */
/*
.navigation {
background: #333;
padding: 1rem;
.nav-list {
display: flex;
gap: 1rem;
list-style: none;
margin: 0; padding: 0;
}
.nav-item {
a {
color: white;
text-decoration: none;
&:hover {
color: #61dafb; // & 기호는 부모(a)를 그대로 치환함
}
}
&.active a {
font-weight: bold;
color: #61dafb;
}
}
}
*/
/* 컴파일된 실제 CSS */
.navigation {
background: #333;
padding: 1rem;
}
.navigation .nav-list {
display: flex;
gap: 1rem;
list-style: none;
margin: 0;
padding: 0;
}
.navigation .nav-item a {
color: white;
text-decoration: none;
}
.navigation .nav-item a:hover {
color: #61dafb;
}
.navigation .nav-item.active a {
font-weight: bold;
color: #61dafb;
}
flexbox 중앙 정렬이나 버튼 스타일처럼 똑같은 CSS 코드 뭉치를 여러 곳에서 반복해서 치고 있진 않나요?
Mixin(믹스인)은 재사용 가능한 코드 블록을 도장처럼 만들어두고 필요할 때마다 찍어내는 기능입니다. 특히 함수처럼 인자(Argument)를 전달받을 수 있어서, 똑같은 구조지만 색상이나 크기만 다른 요소를 찍어낼 때 진가를 발휘합니다.
| 키워드 | 역할 | 사용 예시 |
|---|---|---|
| @mixin | 재사용할 스타일 블록을 정의 | @mixin flex-center { display: flex; ... } |
| @include | 정의된 믹스인을 호출하여 포함 | .box { @include flex-center; } |
| 인자 (Args) | 믹스인에 동적인 값을 전달 | @mixin button($color) { background: $color; } |
<div class="box-container">
<div class="box-small">Small Box</div>
<div class="box-large">Large Box</div>
</div>
/* SCSS Mixin 예시 */
/*
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
@mixin circle($size, $color) {
width: $size;
height: $size;
background-color: $color;
border-radius: 50%;
color: white;
@include flex-center; // Mixin 안에서 다른 Mixin 호출 가능!
}
.box-small {
@include circle(100px, #ef4444);
}
.box-large {
@include circle(150px, #3b82f6);
}
*/
/* 컴파일된 실제 CSS */
.box-container {
display: flex;
gap: 20px;
padding: 20px;
}
.box-small {
width: 100px;
height: 100px;
background-color: #ef4444;
border-radius: 50%;
color: white;
display: flex;
justify-content: center;
align-items: center;
}
.box-large {
width: 150px;
height: 150px;
background-color: #3b82f6;
border-radius: 50%;
color: white;
display: flex;
justify-content: center;
align-items: center;
}