반응형을 잘 만들어내기 위해서는 그리드 디자인이 먼저 규칙성에 맞춰 잘 나와야 한다.
Sass는 CSS가 할 수 없는 일을 할 수 있게 해주는 powerful한 Pre-processor
브라우저가 알아듣는 언어가 아니기 때문에 build를 통해 CSS로 변환해주어야 한다.
CSS에서 중복되거나 반복적으로 나열되는 코드(소위 노가다)를 잘 파악해서 Sass의 함수와 변수로 정리하면 굉장히 효율적으로 사용할 수 있다.
중첩이 깊어지면 구체성 지옥에 빠질 수 있으니 중첩은 불가피한 경우 2 depth까지만 가자.
파일과 mixin 등 분할을 최대한 상세하게 해야 나중에 유지보수가 용이하다.
Sass 문법은 두가지가 존재하는데, 둘다 Sass라고 불러도 된다.
Sass: 초창기에 등장했으며 CSS와 문법이 상이해서 불편하고 허들이 높았다.
Scss: 불편 해소하려 나중에 등장, CSS 로직만 잘 짜면 되는 쉬운 문법.
무겁고 느린 Ruby Sass에서 더 가볍고 빠른 LibSass(Node Sass기반)로 넘어왔지만 요즘은 Dart Sass를 대세로 흘러가는 중
Dart Sass는 표준으로 권장되는 과정 중에 있으니 대세를 따르자.
Dart Sass는 파셀이나 웹팩같은 번들링과정에서 명령어 방식으로 빌드해주는 것에 매우 유용한 버전이다.
파셀과 웹팩은 번들링을 위한 툴인데, 파셀은 비교적 쉬운 반면 customizing을 못한다. webpack은 반면 환경설정이나 빌드 경로 등을 디테일하게 사용자화 가능하다.
sass-study 디렉토리를 생성하고 $npm init -y
$npm install --save-dev sass
또는 $npm i -D sass
로 설치
해당 디렉토리 속 node_modules 안에 sass가 설치되어있는지 확인할 수 있다.
package.json이라는 파일 속에 명령어를 customize 해서 입력
"sass": "sass sass:css"
: sass폴더에 있는 모든 파일을 css폴더에 빌드해서 넣는다.
"watch": "sass --watch sass:css"
: watch로 파일변화를 파악하여 sass 파일이 세이브될때마다 자동으로 css 폴더에 빌드된다.
이제 터미널에 $npm run sass
또는 $npm run watch
등 $npm run {설정한 명령어}
만 입력하면 커스텀 명령어에 저장한 명령이 실행된다.
HEROPY Tech 블로그 Sass(SCSS) 완전정복 참고
자료형에는 파이썬 등의 프로그래밍 언어와 비슷하게 array와 같은 list가 있고, key와 value가 짝지어진 maps도 있다.
연산이 가능하지만, 연산기호 앞뒤에 공백을 꼭 넣어주며, 같은 단위로만 연산을 해주어야 한다. 만약 단위가 다르면 CSS 내장함수인 calc()
을 사용할 것.
연산할 때는 숫자만 넣고 나중에 +{단위값}
을 넣는 것도 방법.
연산기호 중 나눗셈 /
기호는 연산 전체에 괄호를 씌워주지 않으면 에러가 날 수 있다. (CSS 슬래쉬로 인식)
Nesting(중첩): 클래스의 위치와 종속을 명확히 하기 위해 중첩을 사용하는데, 그러면 나중에 구체성 점수 이슈가 생긴다.
중첩 속에서 &
를 사용하면 상위 선택자 클래스명으로 치환된다. 구체성 점수를 높이지 않으면서도 같은 클래스 안에 위치시킬 수 있다.
가독성을 위해 위치할 뿐 중첩과 상관 없는 경우에는 @root .{클래스명}
으로 선택자를 기재한다.
$변수이름: 속성값
으로 간단하게 변수를 지정한다. global scope에 적용되며 같은 변수명으로 나중에 다른 값이 선언될 경우 큰 쿤제가 생기기 때문에 config나 variable 파일을 따로 만들어서 관리하여 변수명이 겹치지 않도록 해야 한다.
한 요소 안에서 선언하면 scope가 해당 요소 내부에만 머무르며, 글로벌 선언하고 싶으면 따로 글로벌 플래그 !global
을 사용해야 한다.
!default
는 할단되지 않은 변수의 초기값을 설정한다. 할당되어 있는 변수가 있다면 기존 할당 값을 사용한다. 내가 작성한 코드와 변수명이 겹쳐서 overwrite 되지 않도록 해준다.
문자보간(interpolation): #{}
안에 변수명을 넣어 코드의 어느 부분이든지 변수값을 넣을 수 있다. 지정한 변수명을 속성 등과 헷갈리지 않게끔 해주는 역할.
@import
: 외부에서 가져온 Sass 파일은 모두 단일 CSS 출력 파일로 병합된다. url()
또는 그냥 겹따옴표 안에 scss파일 위치를 넣는다.
파일 분할(Partials): 따로따로 관리할 파일명 앞에 언더바를 붙이고 style.scss 파일에서 import
언더바를 붙이지 않으면 각각의 scss가 빌드될 때 sourcemap과 parts 폴더를 생성한다.
Sass 구동하는 곳에 parts라는 디렉토리를 만든 후 _header.scss
, _footer.scss
를 만들어 import해보자. import 할때는 언더바나 확장자명을 넣지 않아도 된다.
Scss 파일 빌드할 때 두 가지 스타일 중 하나를 선택할 수 있는데, 선택하지 않고 명령어를 입력하면 default는 expanded이다.
expanded: $sass --style expanded sass:css
로 실행하며 개발자가 보기 편리하게 줄바꿈 등이 되어있다.
compressed: $sass --style compressed sass:css
로 실행, 컴퓨터만 읽으면 되므로 uglify되어있다.
Mixin: 스타일 시트 전체에서 재사용할 CSS 선언 그룹
시안을 받고 component를 잘 뽑아내 공통적인 코드를 뽑아낸 후 mixin을 짠다.
@mixin
으로 정의한 후 적용할 요소에서 @include
로 불러낼 수 있다.
매개변수 없이도 사용이 가능하고, 매개변수를 넣었다면 include 할 때 argument를 넣어 소환시킬 수도 있다.
여러개의 매개변수도 넣을 수 있다.
인자를 넣지 않았을 때의 컴파일 에러 방지를 위해 기본값을 설정해주면 좋다.
@mixin dash-line{$w:1, $c:red){
border: $w + px dashed $c;
}
.container{
@include dash-line(2, blue);
}
# 인자를 안 넣더라도 1px, red로 border의 dash-line mixin이 소환된다.
선언된 mixin 속에 @content;
가 정의되어 있으면 중괄호를 바로 이어넣어 mixin 안에 또다른 mixin이나 속성을 추가할 수도 있다. 이는 media query로 반응형을 만들 때 굉장히 유용.
@mixin lg-screen($breakpoint){
@media screen and (min-width: #{$breakpoint)}{
@content;
}
}
.wrapper{
background-color: yellow;
@include lg-screen(720px){
background-color: pink;
@include dash-line(1, green);
}
}
#스크린 너비가 720px이 넘는 경우 배경색 핑크 속성과, dash-line mixin 적용
함수는 특정 계산 값을 return해준다. (c.f. mixin은 선언부를 return)
include 할 필요 없이 함수명을 넣으면 된다.
Sass가 가진 내장함수도 많으니 built-in module function list를 숙지할 것 (unquote()
, percentage()
, calc()
, rgba()
)
마크업을 데려오기 위해 선생님의 git repository를 clone
해당 디렉토리에 들어가 $npm init -y
, $npm i -D sass live-server
하여 Sass와 Live-server 모듈을 둘다 설치
git을 vscode로 관리하기 위해? .gitignore
파일을 만들고 그 안에 node_modules
와 .vscode
를 적는다 (이건 왜 적는지 모름)
package.json
에 들어가 명령어를 customize한다.
아까처럼 sass와 watch 명령어도 사용자화: "sass":"sass sass:css -I sass"
, "watch": "npm run sass -- --watch"
라이브서버 구동하고 watch하게끔 명령어 추가: "start":"live-server --open=/ | npm run watch"
index.html 파일의 head에 style.css 링크하기
$npm run watch
를 실행하면 CSS 폴더가 생긴다. 이제 sass 작업하면 된다.
Web Cafe 예제의 main contents 부분만 grid로 작업해보자.
논리구조상 트위터가 가장 나중에 나오도록 마크업한다. 즉 마크업 순서는 추천도서, 비디오, 게시판, 인기사이트, 트위터.
각 아이템이 차지하는 column 수는 4, 8, 4, 3, 5
Grid System Calculator로 max-width를 1000, gutter 20px, column 수를 12로 주면 column width 는 65px이 계산된다.
4개 column을 차지하는 추천도서와 게시판의 width는 465 + 3 20 = 320 px
main contents를 flex container로 만들고 flex-flow: row wrap
으로 준다.
flex 를 많이 쓸 경우 utils 폴더 아래 아래와 같이 mixin.scss 파일을 만들어 관리할수도 있다.
@mixin flexbox($direction: row, $wrap: wrap, $justify: flex-start){
display: flex;
flex-direction: $direction;
flex-wrap: $wrap;
justify-content: $justify;
}
favorite (인기사이트)에 flex item의 order:1;
속성을 선언해서 뒤로 보낸다.
마크업 및 레이아웃 (mobile용 대응하기)
view width가 줄어들었을 때 1단으로 되면서 트위터 영역이 제일 밑으로 위치하게 한다.
media query를 이용하며 분기점은 999px까진 모바일, 1000px부터 데스크탑
mixin.scss에서 mixin을 만들어준다. (모바일과 데스크탑 둘다 만들어주었다)
@mixin mobile($breakpoint){
@media screen and (max-width: $breakpoint){
@content;
}
}
@mixin desktop($breakpoint){
@media screen and (min-width: $breakpoint){
@content;
}
}
@include
로 불러와서 모바일인 경우 favorite에 주었던 order값이 취소되게 하려면?
.favorite{
order: 1;
@include mobile(999px){
order:0;
}
}
flex container에 가서 desktop일 땐 아까처럼 되되, mobile일 때는 width가 100% 이 되고 align-item: center;
로 세로정렬이 중앙으로 되게끔 한다.
.appMain{
@include desktop(1000px){
@include flexbox(row, wrap, space-between);
width: 92.5%; #이건 그냥 일반적인 값 준듯
margin: 0 auto;
}
@include mobile(999px){
@include flexbox(row, nowrap, flex-start);
align-items: center;
width: 100%;
}
}
mixin으로 column 너비를 percentage로 만드는 계산식을 만들어보자.
@mixin gridPercentage($column-count:1, $column-total:10, $gutter:10, $container:1000){
$gutter-count: $column-count - 1; #선택영역 속 gutter의 개수
$gutter-total-count: $column-total - 1; #총 gutter의 개수
$gutter-width: $gutter * $gutter-count; #선택영역 속 gutter의 너비
$gutter-total-width: $gutter * $gutter-total-count; #총 gutter의 너비
$gutter-percent: percentage($gutter-width / $container); #선택영역 속 gutter 너비 비율
$column-total-width: $container - $gutter-total-width; # 총 columns 너비
$column-width: ($column-total-width / $column-total); #column 하나 너비
$column-width-percent: percentage($column-width / $container * $column-count);
$column-gutter-width: $column-width-percent + $gutter-width-percent;
width: $column-gutter-width;
}
#1000px container, 20px gutter와, 12개 중 4개 column 차지하는 .book 영역에 해당 mixin을 적용
.book{
@include desktop(1000px){
@include gridPercentage(4, 12, 20px, 1000px);
}
}
#CSS 결과는
.book {
width: 32%;
}
Youtube 영상 반응형으로 퍼오기(iframe 크기 자동조절 trick)
<video>
태그를 통해 플러그인에 의존하지 않고도 브라우저 안에서 바로 재생될 수 있는 비디오가 들어올 수 있게 되었다.
그러나 내 서버가 아닌 youtube나 vimeo 등에서 퍼오는 경우에는 반응형으로 만들기가 어렵다. 이럴 때를 위한 트릭을 한 번 사용해보자.
유투브 공유 중 '퍼가기'를 눌러 iframe 소스를 복사한다.
allow 속성들은 삭제해도 무방. allowfullscreen 말곤 다 지웠다.
일반적인 방법이라면 config에서 video와 iframe의 속성에 width:100%; height: auto;
를 주고 figure{ margin: 0;}
등으로 처리하겠지만, 그렇게 하면 영상 높이가 짤리는 이슈가 생긴다.
iframe 태그를 감싸는 iframe-container
라는 div를 씌우자.
iframe
에 position: absolute;
를 주고 iframe-container
를 position:relative;
주어 offset parent 만들어준다.
iframe
은 top:0; left:0;
로 위치를 고정하고 width:100%; height:100%;
iframe-container
에 padding-top을 영상의 비율에 따라 준다. (4:3인 경우 padding-top: 75%;
, 16:9인 경우 padding-top: 56.25%;
margin과 padding에 %
를 주면 width에 대한 비율로 계산된다.
padding-top을 매번 지정하는 수고를 덜기 위해 아예 클래스 이름을 iframe4to3
이나 iframe16to9
등으로 만들어 대응하는 방법도 있다.
map과 @each
를 이용하여 heading color 바꾸기
각각의 색깔을 클래스명과 속성에 하나하나 지정하기 귀찮을 때 @each
로 해결하기
색깔데이터를 아래와 같이 만들어둔다.
$colors : (
Green: #abd375;
Yellow: #e8ca58;
Brown: #c7b39a;
Skyblue: #6aaee6;
Orange: #eea60a;
)
지정한 색깔데이터를 불러와 key값이 class에 들어가도록 @each를 통해 interpolation 해준다.
@each $color, $text-color in $colors{
.theme#{$color}{
color: $text-color;
}
}
이렇게 속성이 정의된 class name을 필요한 곳(우리의 경우 heading)에 mark-up한다.
list와 @each
를 이용하여 Sprite 기법 쓰기
이번에는 sprite 기법을 쓰려는데 하나하나 좌표 지정하기 귀찮을 때 @each
를 써보자.
준비된 sprite용 파일이 규칙적인 크기와 좌표를 가지고 있어야만 한다.
115px의 높이를 가진(여백은 없음) 그림들을 차례에 맞게 알아서 좌표지정하려면 아래와 같이 리스트와 @each
를 이용한다.
$titles: (Book, Board, News, Favorite, Twitter); #list 생성
@each $title in $titles{
.sprite#{$title}{
$icon-height: -115; #각 아이콘의 높이
$index: index($titles, $title) - 1; #CSS에서는 기본 index가 0이 아니라 1
$position-Y : $icon-height * $index;
background-position: 0 $position-Y+px;
}
}
이렇게 하면 Book부터 각 인덱스에 맞게 Y좌표값이 0, 115, 230 ...인 클래스 이름 .spriteBook
, .spriteBoard
, ..., .spriteTwitter
에 대한 속성이 정의되어 나온다.
이렇게 속성이 정의된 클래스명을 필요한 곳 (우리의 경우 heading 앞 span)에 마크업면 된다.
잠깐 맛만 봤는데도 Sass가 정말 편할거라는 확신이 있지만 아직 익숙하지 않은 나에겐 너무나 큰 숙제이다. 그래도 열심히 익혀서 Sass로 적게 일하고 많은 코드를 짜야지.