[DAY-32] CSS ์ฌํ (4)
๐ ํท๊ฐ๋ ธ๋ & ๋ชฐ๋๋ ๋ถ๋ถ๋ค๋ง ์ ๋ฆฌํ๋ ๋๋ง์ TIL
๐ฏ ๋ชจ๋ ๊ฐ์ ๋ด์ฉ์ ์ ์ง ์์์!
์ค๋์ ์๊ฐ์?
์๋์๋ ์ ์๋ง JavaScript ๊ธฐ๋ณธ ๋ฌธ๋ฒ์ ๋ค์ ๋ฐฐ์ฐ๋ ๋๋์ด์์.
SCSS ๋ญ์ผ .. ์คํ์ผ๊ฒ์ ํ๋ช
์ธ๋ฐ์?
์ด๊ฑธ ์ ๋ง ๋ชฐ๋๋ค๊ตฌ์???? ์ ๋ง ์ค์ฒฉ๋ฌธ ์์ฐ๊ณ ์ผ์ผํ ๋ค ์์ฑํ๊ณ ์์์ด์??!!???!!!??
๋ ์ด์ฌํ ๊ณต๋ถํ๊ฒ ์ต๋๋ค..
[1] Sass(SCSS)
Sass
(SCSS
)๋ CSS Preprocessor์
๋๋ค.
Sass
์ SCSS
๋ ์ฝ๊ฐ์ ์ฐจ์ด๊ฐ ์กด์ฌํฉ๋๋ค.
ํ๋จ๊ณผ ๊ฐ์ด SCSS
๋ ์ค๊ดํธ๋ก ๋ฒ์๋ฅผ ์ง์ ํด์ฃผ๋ ๊ธฐ๋ฅ, ์ธ๋ฏธ์ฝ๋ก ์ฌ์ฉ์ด ํฌํจ๋์ด ์์ผ๋ฉฐ
Sass
๋ ์ค๊ดํธ์ ์ธ๋ฏธ์ฝ๋ก ์ ์ฌ์ฉํ์ง ์๊ณ , ๋ค์ฌ์ฐ๊ธฐ ๊ฐ๋
์ด ์ค์ํฉ๋๋ค.
/* SCSS Syntex */
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
display: inline-block;
}
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}
/* Sass Syntex */
nav
ul
margin: 0
padding: 0
list-style: none
li
display: inline-block
a
display: block
padding: 6px 12px
text-decoration: none
[1-1] ์ฃผ์, ์ค์ฒฉ
SCSS
๋ ๊ธฐ์กด์ CSS
์ ์ฃผ์ ํํ๊ฐ ์ฝ๊ฐ ๋ค๋ฆ
๋๋ค.
//
ํํ์ ์ฃผ์์ ํ๋ ๋ ์ ๊ณตํ๋ฉฐ, ํด๋น ์ฃผ์์ ์ปดํ์ผ ๋ ๊ฒฐ๊ณผ์ ํฌํจ๋์ง ์์ต๋๋ค.
[1] ์ฃผ์
Sass
์ ๊ฒฝ์ฐ, ์ฌ๋ฌ ์ค ์ฃผ์์ ์ฌ์ฉํ ๋ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์๋นํ ์ค์ํฉ๋๋ค.
[2] ์ค์ฒฉ
SCSS
๋ฅผ ์ฌ์ฉํ๋ฉด ์์ ์์์ ๋ฐ๋ณต์ ์ธ ์์ฑ์, ์ค์ฒฉ์ผ๋ก ๊ฐ๋จํ๊ฒ ์์ฑํ ์ ์์ต๋๋ค.
์ด๋ &
๋ ์์ ์ ํ์์ ์๋ฏธ์
๋๋ค.
&
๋ถ๋ถ์ ์์ ์์๊ฐ ๊ธฐ์
๋จ์ ํ์ธํ ์ ์์ต๋๋ค.
๋ํ ๋ณ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ณ์๋ ์์ $
๊ธฐํธ๊ฐ ๋ถ์ต๋๋ค.
๋จ ๋ณ์์ ์ค์ฝํ๋ฅผ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
์ค์ฝํ ๋ด์ ๋ณ์๋ฅผ ํ์ฉํ๋ ์์์ ์์ ์ ํ์๊ฐ ๋ถ๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด @at-root
๋ผ๋ ๊ท์น์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ณ์๋ฅผ ์ฌ์ฉํ ์ ์๋ฏ, ์์ฑ์ ์ด๋ฆ์ด ๊ฒน์น ๊ฒฝ์ฐ์๋ ๋ค์ฌ์ฐ๊ธฐ ํ์์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค.
๋ค์ฌ์ฐ๊ธฐ์ ์์ ์์ฑ์ด ํฉ์ณ์ ธ ํ๋์ ์์ฑ๋ ์์ฑ๋ค์ ์์ฑํ ์ ์์ต๋๋ค.
์ฌ๋ฌ ์ ํ์๋ฅผ ํ๋ฒ์ ์์ฑํ ์ ์์ต๋๋ค.
์๋์ผ๋ก ul์ ํ์ ์์๋ค, ol์ ํ์ ์์๋ค๋ก ๋ฌถ์ด์ฃผ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
[1-2] ๋ณ์, ๋ฐ์ดํฐ, ์ฐ์ฐ์
[1] ๋ณ์
์์์๋ ๊ฐ๋จํ ์ดํด๋ดค๋ฏ์ด, $
๋ก ์์ํ๋ ๋ณ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ณ์๋ ์ฌํ ๋น์ด ๊ฐ๋ฅํฉ๋๋ค.
.box-a {
$h: 200px; // ๋ณ์์ ๋ฒ์๋ ์์ ์ด ์ ์ธ๋ ๋ธ๋ก ์์์๋ง ์ ํจํฉ๋๋ค.
width: $w;
height: $h;
margin: $w;
}
- !global
!global
์ ์ฌ์ฉํ๋ฉด ๋ณ์์ ์ ํจ ๋ฒ์๋ฅผ ์ ์ญ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค.
๋ง์ฝ ์ฌํ ๋น ๋ณ์๋ฅผ !global
์ผ๋ก ์ง์ ํ ๊ฒฝ์ฐ, ํ์ ๋ถ๋ถ์์๋ ์ ๋ถ ํด๋น ๊ฐ์ผ๋ก ๋ฎ์ฌ์์์ง๊ฒ ๋ฉ๋๋ค.
.box-a {
$h: 200px !global;
width: $w;
height: $h;
margin: $w;
}
.box-b {
height: $h;
}
.box-a {
width: 100px;
height: 200px;
margin: 100px;
}
.box-b {
height: 200px; /* ๋ณ์๊ฐ ์ ์ธ๋ ์์ ๋ฐ์ ๋ค๋ฅธ ์์์์๋ $h๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. */
}
- !default
์ฌํ ๋น ์, ํด๋น ์ ์ญ ๊ฐ์ ์ ์ง์ํค๊ธฐ ์ํด์ !default
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
$primary: blue;
.box {
$primary: orange !default; // ๋ง์ฝ default๊ฐ์ด ์์ผ๋ฉด orange๊ฐ ํ ๋น๋ฉ๋๋ค.
background-color: $primary;
}
.box {
background-color: blue;
}
- ๋ณด๊ฐ
๋ณด๊ฐ์ ๋ณ์ ํ ๋น๊ณผ ๋น์ทํ๋ฉฐ #{๋ณ์๋ช
}
์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ํ ์์ ์ด๋ฆ ์ฆ ์ผ๋ฐ์ ์ธ ๋ชจ๋ ๋ฌธ์์ด์ ๋ฃ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
[2] ๋ฐ์ดํฐ
SCSS
์์ ์ฌ์ฉํ ์ ์๋ ๋ฐ์ดํฐ(๋ณ์)์๋ ์ฌ๋ฌ ํ์์ด ์์ต๋๋ค.
// Numbers
$number1: 1;
$number2: 0.82;
$number3: 20px;
$number4: 2fr;
// Strings
$string1: bold;
$string2: absolute;
$string3: "assets/images/";
// Colors
$color1: blue;
$color2: yellowgreen;
$color3: rgba(255, 0, 0, 0.5);
$color4: #ffff00;
// Booleans
$boolean1: true;
$boolean2: false;
// Null
$null: null;
// Lists
$list1: (10px, 20px, 30px);
$list2: 10px, 20px, 30px;
$list3: 10px 20px 30px;
$list4: apple banana cherry;
// Maps
$map1: (
key: value,
);
$map2: (
a: apple,
b: banana,
c: cherry,
);
[3] ์ฐ์ฐ์
- ์ฐ์ ์ฐ์ฐ์
SCSS
์์๋ ์ฐ์ ์ฐ์ฐ์(+, -, *, /, %
)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋จ /
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ ๋ ์ฃผ์ํด์ผ ํฉ๋๋ค.
๋ณดํต CSS์์๋ background, font
์ ๊ฐ์ด ๋ ๊ฐ ์ด์์ ์์ฑ ๊ฐ์ ํ๋ฒ์ ์์ฑํ ์ ์๋ ์์ฑ์ด ์กด์ฌํฉ๋๋ค.
/* background-position: 100px 100px;
background-size: 200px 200px; */
background: 100px 100px / 200px 200px;
/* font-size: 10px;
line-height: 32px; */
font: 16px / 32px serif;
์ด๋๋ ๊ตฌ๋ถ์๋ก /๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, ๋๋๊ธฐ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ๋ฐ๋ก ์ฒ๋ฆฌ๋ฅผ ํด์ค์ผํฉ๋๋ค.
/* 1. ์๊ดํธ๋ก ๊ฐ์ธ๊ธฐ (๊ถ์ฅ) */
top: (20px / 2);
/* 2. ๋ณ์ ์ฌ์ฉ */
$a: 20px;
top: $a / 2;
/* 3. ๋ค๋ฅธ ์ฐ์ฐ์์ ํผํฉํ์ฌ ์ฌ์ฉ */
top: 20px / 2 + 0px;
- calc()
๋จ์๊ฐ ๋ค๋ฅธ ๊ฐ๋ค์ ์ฐ์ฐ์ ์ด์ฉ์ ์ํด์ ์ฌ์ฉํ๋ ํจ์์ ๋๋ค.
left: calc(
100% - 50px
); // 100%์ ํด๋นํ๋ ๊ฐ์์ 50px ๋บ ๊ฐ์ด left์ ์ ์ฉ๋ฉ๋๋ค.
- ๋น๊ต ์ฐ์ฐ์
SCSS
์์ ๋น๊ต ์ฐ์ฐ์(==, โ , <, >, โค, โฅ
)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ฌผ๋ก ์กฐ๊ฑด๋ฌธ๊ณผ ํจ๊ป ์ฌ์ฉ๋ฉ๋๋ค.
.box {
$w: 100px;
@if ($w == 100px) {
width: $w;
} @else {
width: 200px;
}
}
- ๋ ผ๋ฆฌ ์ฐ์ฐ์
SCSS
์์ ๋
ผ๋ฆฌ ์ฐ์ฐ์(and, or, not
)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
.box {
$w: 100px;
$h: 200px;
$b: false;
@if (not $b and $h >= 100px) {
width: $w;
height: $h;
}
}
[1-3] @mixin
@mixin
๊ณผ @include
๋ฅผ ์ฌ์ฉํ์ฌ ์ฌํ์ฉ ํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
large-text
์์ ๋ชจ๋ ์คํ์ผ์ด box-a
์ ์ ์ฉ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๋ํ ๋ง์น JS์ ํจ์์ฒ๋ผ, ๋งค๊ฐ๋ณ์๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค.
box-a
์ ํฐํธ ์ฌ์ด์ฆ๋ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋ 20px, box-b
๋ 40px์์ ํ์ธํ ์ ์์ต๋๋ค.
์ด๋ ๊ธฐ๋ณธ๊ฐ์ ์ง์ ํ ์ ์์ต๋๋ค.
@mixin large-text($size: 30px) {
font-size: $size;
font-weight: bold;
font-family: sans-serif;
color: tomato;
}
.box-a {
width: 100px;
height: 100px;
@include large-text; // ๋งค๊ฐ๋ณ์๊ฐ ์์ผ๋ฏ๋ก $size์ ๊ธฐ๋ณธ๊ฐ์ธ 30px๊ฐ ์ง์
}
@mixin
์ผ๋ก ์์ฑ๋ ์ฌํ์ฉ ์ฝ๋๋ ์ค์ฒฉ์ด ๊ฐ๋ฅํฉ๋๋ค.
@mixin reset-margin {
margin: 0;
padding: 0;
box-sizing: border-box;
}
@mixin section {
font-size: 20px;
line-height: 1.4;
color: blue;
h1 {
font-size: 40px;
font-weight: bold;
@include reset-margin;
// mixin์ผ๋ก ์์ฑ๋ ์ฌํ์ฉ ์ฝ๋ ์์์, ๋ค๋ฅธ ์ฌํ์ฉ ์ฝ๋๋ฅผ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค.
&::after {
content: "!!";
}
}
}
[1] ๊ฐ๋ณ ์ธ์
๋งค๊ฐ๋ณ์๋ก ๋ค์ด์ฌ ๊ฐ์ ๊ฐฏ์๋ฅผ ์์ธกํ์ง ๋ชปํ ๋, ๊ฐ๋ณ ์ธ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
@mixin bg($w, $h, $b...) {
// ...๋ฌธ๋ฒ์ ์ฌ์ฉํฉ๋๋ค.
width: $w;
height: $h;
background: $b;
}
.box {
@include bg(
100px,
200px,
url("/images/a.png") no-repeat center,
url("/images/b.png") repeat x,
url("/images/c.png") repeat-y center / contain
);
}
๋ํ JS์ ๊ตฌ์กฐ ๋ถํด ํ ๋น์ ๊ฐ๋ ์ฒ๋ผ, ํด๋น ๊ฐ๋ณ ์ธ์์ ๊ฐ๋ค์ ํ๋์ฉ ํ ๋น๋ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
@mixin spread($t, $r, $b, $l) {
margin-top: $t;
margin-right: $r;
margin-bottom: $b;
margin-left: $l;
}
.box {
$m: 10px 20px 30px 40px;
@include spread($m...); // ...๋ฌธ๋ฒ์ ์ฌ์ฉํฉ๋๋ค.
}
๋ฐ๋ผ์ JS์ ์ ๊ฐ ์ฐ์ฐ์์ฒ๋ผ ...
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
[2] ํค์๋ ์ธ์
mixin
๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ ๋, ์์์ ์๊ด์์ด ํน์ ๋งค๊ฐ๋ณ์์๋ง ๊ฐ์ ์ ๋ฌํ๊ณ ์ถ์ผ๋ฉด ํค์๋ ์ธ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
@mixin pos($p, $t: null, $r: null, $b: null, $l: null) {
position: $p;
top: $t;
right: $r;
bottom: $b;
left: $l;
}
.absolute {
width: 100px;
height: 100px;
@include pos(absolute, $t: 100px, $l: 50px);
}
[3] @content
mixin
์ ์ฌ์ฉํ ๋, ๋ค์ชฝ์ ์ ์ ์ค๊ดํธ ์ฌ์ด์ ์ถ๊ฐ์ ์ธ ์คํ์ผ๋ค์ @content
๋ฅผ ์ฌ์ฉํด์ ํน์ ์์น์ ์ฝ์
ํ ์ ์์ต๋๋ค.
@mixin icon($url) {
&::after {
content: url($url);
@content; // ์ด๊ณณ์ ์ฝ์
}
}
.box {
@include icon("/images/icon.png") {
// ์ถ๊ฐ์ ์ธ ์คํ์ผ ๋ช
์
position: absolute;
top: 0;
left: 50px;
}
}
๋ฐ๋๋ก ๊ฐ์ ๊บผ๋ด์ฌ ์๋ ์์ต๋๋ค.
... @media all and (max-width: map.get($breakpoints, $name)) {
@content (777); // 777์ ์ ๋ฌํด์ค๋๋ค.
}
...
// using ํค์๋๋ฅผ ์ฌ์ฉํด์ $c์ ํด๋น @content์์ ์ ๋ฌ๋ ๋ณ์๋ฅผ ๋ด์ ์ ์์ต๋๋ค.
@include media(lg) using($c) {
width: 300px;
height: 300px;
_debug: $c;
}
- โsass:mapโ module
๋ค์ ์๊ฐ์ ๋ ์์ธํ ์์๋ณผ ๋ถ๋ถ์ด์ง๋ง, ๊ฐ๋ตํ๊ฒ map์ผ๋ก ์์ฑ๋ SCSS map๋ค์ ๊ฐ value๋ฅผ ์กฐํํ ์ ์๊ฒ ํด์ค๋๋ค.
map.get(map ๊ฐ์ฒด, ํค๊ฐ)
๊ณผ ๊ฐ์ ํํ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
@use "sass:map";
@mixin media($name) {
$breakpoints: (
sm: 576px,
md: 992px,
lg: 1400px,
);
@media all and (max-width: map.get($breakpoints, $name)) {
@content; // ์ถ๊ฐ์ ์ผ๋ก ์
๋ ฅํ ์คํ์ผ ๋ธ๋ก์ด ์ ์ฉ๋ฉ๋๋ค.
}
}
.box {
width: 400px;
height: 400px;
@include media(lg) {
width: 300px;
height: 300px;
}
@include media(md) {
width: 200px;
height: 200px;
}
@include media(sm) {
width: 100px;
height: 100px;
}
}
.box {
width: 400px;
height: 400px;
}
@media all and (max-width: 1400px) {
.box {
width: 300px;
height: 300px;
}
}
@media all and (max-width: 992px) {
.box {
width: 200px;
height: 200px;
}
}
@media all and (max-width: 576px) {
.box {
width: 100px;
height: 100px;
}
}
@media all and (max-width: 992px) {
.section {
width: 450px;
}
}
๊ฐ ์์ ์์ ์ถ๊ฐ๋ก ์ ๋ ฅํ ์คํ์ผ ๋ธ๋ก์ด ์ ์ ์ฉ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
[1-4] Sass @include, @mixin
Sass
์์์ @include
๋ +
๊ธฐํธ์ด๋ฉฐ @mixin
์ =
๊ธฐํธ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
@mixin icon($url) {
&::after {
content: url($url);
}
}
.box {
@include icon("/images/icon.png");
}
=icon($url)
&::after
content: url($url)
.box
+icon("/images/icon.png")
๋๊ธ๋จ๊ธฐ๊ธฐ