CSS
는 웹 페이지 스타일 및 레이아웃을 정의하는 스타일시트 언어다. CSS는 좋은 사용자 경험을 제공하기 위한 도구다.
스타일은 link 태그로 css 파일을 연결하거나 요소 속성으로 직접 스타일을 작성 또는 style 태그 안에 작성해 적용할 수 있다.
💡 CSS 스타일 적용 방법 중 하나에 집중하기 위해 파일이나 구간을 구분하는 관심사 분리 측면에서 인라인 스타일과 내부 스타일 시트는 권장하지 않는다.
글꼴 크기, 화면 크기 등 크기를 다룰 때는 크기의 단위를 신경써야 한다. 크기의 단위는 절대 단위
와 상대 단위
가 있다.
px
, pt
등%
, em
, rem
, ch
, vw
, vh
등기기나 브라우저 사이즈 등 환경의 영향을 받지 않는 절대적인 크기로 정하는 경우 px
(픽셀)을 사용한다. 픽셀은 고정된 절대 단위이기 때문에 사용자 접근성이 불리할 수 있다. 또한, 모바일 기기처럼 작은 화면이면서 고해상도인 경우에 뚜렷하게 출력되지 않을 수 있어 적합하지 않다. 픽셀은 인쇄와 같이 화면 사이즈가 정해진 경우에 적합하다.
일반적으로 상대 단위인 rem
을 사용한다. root의 글자 크기, 즉 브라우저의 기본 글자 크기가 1em
이며, 이 값을 기준으로 글자 크기를 키우거나 줄일 수 있다. 또한, 사용자가 설정한 기본 글꼴 크기를 따르기 때문에 픽셀보다 사용자 접근성에 유리하다. 이때 em
은 부모 엘리먼트에 따라 상대적으로 크기가 변경되어 계산이 어렵다.
디바이스의 너비에 따라 유동적인 레이아웃이 적용되는 반응형 웹을 만들 때는 디바이스 크기별로 CSS를 다르게 적용해야 한다. 이때 디바이스의 크기를 나누는 기준을 보통 px
로 정한다.
화면 너비나 높이에 따른 상대적인 크기가 중요한 웹의 경우 vw
, vh
를 사용한다. 웹사이트의 보이는 영역을 Viewport
라고 하는데, vw와 vh는 각각 viewport weight와 viewport height를 의미한다. 1vw(vh)는 보이는 영역 너비(높이)의 1/100을 뜻한다. 참고로 %
의 경우 HTML이 차지하는 모든 영역(현재 보이지 않지만 스크롤했을 때는 보이는 영역까지)을 포함한 비율이다.
100vw
, 100vh
를 적용한 p 태그
vw, vh를 적용하면 보이는 영역만큼 크기를 차지하게 된다. 따라서 웹의 크기를 변형해도 항상 전체 화면이 꽉 차게 나타난다.
100%
를 적용한 p 태그
너비와 높이를 100%로 설정한다면 html 파일이 차지하는 영역만큼을 가득 채워 나타난다. html 파일에 하나의 p 태그만 있어 p태그가 있는 영역 부분 정도가 html 파일이 차지하는 영역이 된다.
박스는 줄바꿈이 되는 block 박스
와 줄바꿈이 되지 않고 크기를 지정할 수 없는 inline 박스
가 있으며 이 두 가지 박스의 특징이 섞여 줄바꿈이 일어나지 않지만 크기는 지정할 수 있는 inline-block 박스
가 있다.
대표적인 block 박스로는 h1
, p
, div
등이 있고 inline 박스로는 span
이 있다. block 박스는 기본적으로 100%의 너비를 차지하는 반면, inline 박스는 글자가 차지하는 만큼의 너비를 갖는다.
줄바꿈이 일어나지 않으면서 높이와 너비를 설정하고 싶은 경우, inline 박스에 display: inline-block
속성을 추가하면 된다.
박스의 너비는 속성으로 지정한 width 뿐만 아니라 테두리 값인 border까지 포함해 측정한다.
💡 박스의 너비: contents + padding + border
테두리의 너비까지를 박스의 너비로 계산하기 때문에 contents의 너비인 width 속성으로 레이아웃을 디자인하면 본 의도와 달라질 수 있다. 이때 padding과 border를 포함해 박스 크기를 계산하게 만들기 위해서 다음과 같은 속성을 적용할 수 있다.
* {
box-sizing: border-box;
}
content-box
: content의 너비가 박스의 너비 (실제로 차지하는 너비보다 작은 값일 수 있음)border-box
: content부터 border까지 포함한 박스의 너비css에서 html 요소를 선택해 디자인을 입히기 위한 수단으로 selector
를 사용한다. 셀렉터의 종류는 다음과 같다.
전체 셀렉터
: 문서의 모든 요소 선택* { }
태그 셀렉터
: 같은 태그명을 가진 모든 요소 선택h1 { }
div { }
span, li { }
id 셀렉터
: 해당 id 속성을 갖는 요소 선택#id { }
class 셀렉터
: 같은 class 속성을 갖는 모든 요소 선택.class-name { }
attribute 셀렉터
: 같은 속성을 가진 요소 선택a[href] { }
p[class~="out"] { }
section[id^="sect"] { }
div[class*="w"] { }
자식 셀렉터
: 첫 번째로 입력한 요소의 바로 아래 자식인 요소를 선택header > p { } <!-- header 태그의 한 단계 아래 p 태그 선택 -->
후손 셀렉터
: 첫 번째로 입력한 요소의 후손까지 선택header span { } <!-- header 태그의 한 단계 아래부터 존재하는 모든 span 태그 선택 -->
<header>
<span>a</span> <!-- 선택(자식이자 후손) -->
<div>
<span>b</span> <!-- 선택(후손) -->
<div>
<span>c</span> <!-- 선택(후손) -->
</div>
</div>
</header>
형제 셀렉터
: 같은 부모 요소를 공유하면서, 첫 번째 입력한 요소 뒤에 오는 두 번째 입력한 요소를 모두 선택section ~ p { }
<article>
<section></section>
<p></p> <!-- 선택(section과 부모가 동일한 p 태그이기 때문에 형제) -->
<p></p> <!-- 선택(section과 부모가 동일한 p 태그이기 때문에 형제) -->
<p></p> <!-- 선택(section과 부모가 동일한 p 태그이기 때문에 형제) -->
</article>
인접 형제 셀렉터
: 같은 부모 요소를 공유하면서, 첫 번째 입력한 요소 바로 뒤에 오는 두 번째 입력한 요소 선택section + p { }
<article>
<section></section>
<p></p> <!-- 선택(section과 부모가 동일하며 첫 번째로 오는 p 태그이기 때문에 인접 형제) -->
<p></p>
<p></p>
</article>
가상 클래스 셀렉터
: 요소의 상태 정보에 기반해 요소 선택a:link { } // 링크가 클릭되지 않은 않은 a 요소
a:visited { } // 링크가 클릭된 적이 있는 a 요소
a:hover { } // 마우스가 a 요소 위에 올라온 경우
a:active { } // 링크가 클릭된 상태인 경우
a:focus { } // 포커스가 들어와있는 경우
UI 요소 상태 셀렉터
input:checked + span { } // 체크 상태일 때 선택
input:enabled + span { } // 사용 가능한 상태일 때 선택
input:disabled + span { } // 사용 불가능한 상태일 때 선택
p:first-child { }
ul > li:first-child { }
ul > li:nth-child(2) { }
ul > li:last-child { }
p:first-of-type { }
div:last-of-type { }
ul:nth-of-type(2) { }
p:nth-last-of-type(1) { }
부정 셀렉터
input:not([type="password']) { }
div:not(:nth-of-type(2)) { }
정합성 확인 셀렉터
input[type="text"]:valid { }
input[type="text"]:invalid { }