IT/언어

[SCSS] SCSS의 mixin 기초

개발자 두더지 2023. 8. 20. 21:58
728x90

일본의 한 블로그 글을 번역한 포스트입니다. 오역 및 의역, 직역이 있을 수 있으며 틀린 내용은 지적해주세요.

 

 이 포스트에서는 자신의 프로젝트에 맞게 mixin을 만들 수 있는 최소한의 지식에 대해 설명하고자한다.

 

mixin이란?


 속성이나 값을 세팅하여 정리할 수 있는 기능이다.

@mixin mixin명 {
  속성: 값;
}

  @mixin mixin명으로 {}내에 정리하고 싶은 속성과 값을 기재한다. 이것으로 아이템화된다.

 정리된 mixin은 @include mixin명으로 기재하면 호출할 수 있다.

@mixin p-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50% , -50%);
}
div {
  @include p-center;
}
/* 컴파일 결과(style.css) */
div {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50% , -50%);
}

mixin사용의 메리트

  • 사이트내에서 반복해서 사용하는 공통의 스타일이 있다면 몇 번이고 동일한 코드를 작성하는 수고가 없어진다.
  • 수정은 mixin 한 부분만 하면 한꺼번에 변경된다.

 

mixin에서 사용할 수 있는 문자

  한자등의 다양한 문자를 사용할 수 있지만, 사용할 수 없는 문자 규칙이 세 가지 존재한다.

  • 숫자로 시작하는 문자
  • 연속해서 연결된 하이픈으로 시작하는 문자
  • @등의 기호
@mixin 123alphabet
@mixin --shadow
@mixin alpha@bet

 

 

mixin의 기본적인 사용법


여기서 부터는 mixin을 더욱 편리하고 유연성 있게 사용하기 위한 기본적인 사용법에 대해서 소개하고자 한다.

 

인수 사용하기

mixin에서는 인수를 사용할 수 있다. 

@mixin mixin명($인수) {
  //스타일을 정의
}

셀렉터 {
  @include mixin名($인수);
}

 mixin명($인수)를 작성하여 mixin를 만들고, 호출할 때는 include mixin명($인수)으로 쓰면 쓸 ㅅ ㅜ있다.

@mixin base-color($color) {
  color: $color;
}

p {
  @include base-color(#333333);
}

 예를 들면 다음과 같다.

1. 속성은 color를 설정하지만, 값은 유연하게 바꾸고 싶으므로 변수로 둔다.

2. 값은 호출시에 정하므로, mixin에는 인수(속성 값 = 변수)가 필요하다.

3. 호출했을 때 처음에 값을 지정한다.

 인수를 사용한 mixin을 만들 때(사용할 때)는 이와 같이 작성한다. 그리고 호출 시에 인수 값을 쓰지 않으면 컴파일 에러가 발생한다. 

 

인수의 초기값을 지정

@mixin base-color($color:#333333) {
  color: $color;
}

 이 와같이 초기값을 정해두는 것도 가능하다. 

p {
  @include base-color;
}

/* 컴파일 결과(style.css) */
p {
  color: #333333;
}

 이 경우에는 호출시에 값을 지정하지 않아도 초기값으로 컴파일되므로 에러가 발생하지 않는다. 그러나 어디까지나 초기값이므로 호출시에 호출시 다른 값을 지정하여 덮어 쓰는 것이 가능하다.

p {
  @include base-color(#ffffff);
}

/* 컴파일 결과(style.css) */
p {
  color: #ffffff;
}

 

여러 개의 인수를 정의

@mixin base($color,$w-num,$h-num) {
  color: $color;
  width: $w-num;
  height: $h-num;
}

 여러 개의 값을 변수화하면 수만 인수로 전달하면 된다.

div {
  @include base(#333333,600px,400px);
}

/* 컴파일 결과(style.css) */
div {
  color: #333333;
  width: 600px;
  height: 400px;
}

 컴파일시에 호출했을 때 지정한 순서대로 값이 컴파일되므로 mixin의 인수로 전달한 순서와 동일하게 맞추도록하자. 인수가 여러 개일때도 각각의 초기값을 지정해두는 것이 가능하다.

@mixin base($color:red,$w-num:300px,$h-num:300px) {
  color: $color;
  width: $w-num;
  height: $h-num;
}
div {
  @include base;
}

/* 컴파일 결과(style.css) */
div {
  color: red;
  width: 300px;
  height: 300px;
}

 그리고 값을 덮어 쓸 수 있다.

 

특정 인수의 값만 덮어쓰기

 여러개 의 인수를 지정했을 경우, "특정의 속성값만 바꾸고 싶다"라는 경우도 있을 것이다. 그 경우에는, 이와 같이 호출시에 해당 인수와 값만 개별 지정하면 OK이다.

@mixin base($color:red,$w-num:300px,$h-num:300px) {
  color: $color;
  width: $w-num;
  height: $h-num;
}

div {
  @include base($w-num:600px);
}

/* 컴파일 결과(style.css) */
div {
  color: red;
  width: 600px; /* 초기값300px가 덮어씌여진다 */
  height: 300px;
}

 

가변장인수(...)으로 지정

 mixin은 기본 인수 1개에 대해서 1개의 값만 지정할 수 있다. 그러므로 값을 여러 개 지정할 수 있는 속성을 사용하고 싶을 때에 곤란하다 (box-shadow나 text-shadow, font-family등의 경우).

@mixin mixin-box($box) {
  box-shadow: ($box);
}

// 하나의 속성에 대해 여러 개의 값을 지정하면 에러가 된다!
div {
  @include mixin-box(3px 3px #333, 1px 1px #888);
}

 이럴 때에 가변장인수를 사용할 수 있다. 가변장인수는 ... 점 세개를 붙여서 지정하는 것을 의미한다.

@mixin mixin-box($box...) {
  box-shadow: ($box);
}

div {
  @include mixin-box(3px 3px #333, 1px 1px #888);
}

/* 컴파일 결과(style.css) */
/* 가변 장인수를 사용하고 있으므로 값이 그대로 컴파일된다! */
div {
    box-shadow: 3px 3px #333, 1px 1px #888;
}

또한, 속성의 특성에 한정하지 않고, 가변장인수를 사용하는 테크닉이 있으므로 소개하겠다.

@mixin base($color,$w-num,$h-num) {
  color: $color;
  width: $w-num;
  height: $h-num;
}

 여러 개의 인수가 전달되어 있고, 초기값도 설정되어있지 않은 mixin이 있다고하자.

$values : red, 300px,300px;

 가변장인수를 준비해두고($values), 

div {
  @include base($values...);
}

/* 컴파일 결과(style.css) */
div {
  color: red;
  width: 300px;
  height: 300px;
}

 호출했을 때에 변수($values)를 인수로 지정하여 가변장인수를 쓰며, 그대로 값이 컴파일 된다.

 

 

Sass의 기능을 사용해 mixin을 레벨업하기


 지금부터는 다른 Sass의 기능과 함께 합쳐서 보다 실전적인 mixin의 사용법에 대해서 얘기하고자 한다.

 

@if로 스타일을 나누기

 전달된 인수로 처리 내용 자체를 나누고 싶은 경우는 @if를 사용한다.

@mixin column($sp:false) {
	display: flex;
	@if($sp) {
		flex-direction: column;
	}
}

 

@content로 컨텐츠 블록을 전달하기

 @content는 mixin에 대해서 컨텐츠 블록을 전달하기 위한 기능이다. 컨텐츠 블록은 @content를 기재한 부분에 전개된다. 실전 예시를 살펴보자.

 

@mixin tab() {
	@media screen and (max-width: 768px) {
		@content;
	}
}
@mixin sp() {
	@media screen and (max-width: 599px) {
		@content;
	}
}

 두 종류의 미디어 쿼리를 mixin화하고있다. 그리고 미디어 쿼리의 {}내에 @content를 지정하고 있다.

div {
	margin: 0 auto;
	padding: 0 20px;
	width: 33.3%;
	
	@include tab {
		width: 50%;
	}
	@include sp {
		width: 100%;
	}
}

 보통의 mixin와 동일하게 @include로 호출해보면,

/* 컴파일 결과(style.css) */
div {
  margin: 0 auto;
  padding: 0 20px;
  width: 33.3%;
}

@media screen and (max-width: 768px) {
  div {
    width: 50%;
  }
}

@media screen and (max-width: 599px) {
  div {
    width: 100%;
  }
}

 

 이렇게 컴파일된다.

 미디어 쿼리 {}이라는 한 세트에 @content를 지정하는 것으로, mixin으로 호출한 셀렉터에 대해서 컨텐츠 블록이 전달되어, 셀렉터 전체를 감싸는 형태로 전개시킬 수 있다.

@media screen and (max-width: 768px) {
  @content;
}

/* 셀렉터 안에 mixin를 호출하고 있으나 */
div {
	@include tab {
		width: 50%;
	}
}

/* @content의 위치에 셀렉터부터 한 세트가 전대된다. */
@media screen and (max-width: 768px) {
  div {
    width: 50%;
  }
}

 

 

@extend와의 차이


 다른 곳에서 지정한 스타일 세트를 상속하여 호출하는 기능으로 extend라는 것이 있다. mixin과 어느정도 용도가 비슷하므로 비교되는 경우도 있으나, 여기서 차이점에 대해서 간략하게 살펴보고자한다.

.box {
  background-color: #000;
}

.extendBox {
  @extend .box;
}

 예를 들어 위와 같이 div{~}로 만든 룰 세트가 있는 경우, 다른 셀렉터로 @extend로서 상속하고 싶은 요소 (위의 경우는 .box)를 지정하면,

/* 컴파일 결과(style.css) */
.box, .extendBox {
  background-color: #000;
}

이 처럼 스타일을 상속하여 컴파일 될 수 있다. 또한, @extend에 포함된 모든 스타일을 상속한다.

.box {
  background-color: #000;
	.box-child {
		width: 100%
	}
}

.extendBox {
  @extend .box;
}

 위와 같이 .box의 하층에 다른 세트(.box-child 클래스)를 기재하고 있었다고 해도,

/* 컴파일 결과(style.css) */
.box, .extendBox {
  background-color: #000;
}
.box .box-child, .extendBox .box-child {
  width: 100%;
}

 중첩되어 있는 스타일별로 정리하여 상속하고 컴파일한다.

 @extend는 몇 번이고 동일한 스타일을 기재하는 작업을 없애는 것이 가능한 편리한 기능이지만 주의할 점이 있다. 위의 예에서 언급한 것처럼 포함된 모든 스타일이 그룹핑되어 컴파일되므로 계층이 깊어지면 코드가 헷갈리기 쉬워진다.

 또한 원래 .box클래스만 있으면 됐지만, @extend를 사용하기 위해 불필요한 클래스도 추가하므로써 낭비하게 된다. mixin이라면 

@mixin box($box-child:false) {
  background-color: #000;
	@if($box-child) {
		width: 100%
	}
}

.box {
  @include box(box-child);
}

 @if로 box-child이라는변수를 조건 분기에 사용하면, 

/* 컴파일 결과(style.css) */
.box {
  background-color: #000;
  width: 100%;
}

 같은 화면이라도 더욱 간략하게 쓸 수 있다.


 참고자료

https://pengi-n.co.jp/blog/sass-mixin/

 

728x90