오늘은 마크업의 꽃, HTML 문서에 스타일을 부여할 수 있는 CSS에 대해 알아보자!
CSS
- 웹페이지 스타일 및 레이아웃을 정의하는 스타일시트 언어
- HTML구조의 UX를 제공하기 위해 UI 및 레이아웃을 적절히 구성하여 멋진 웹페이지 완성이 가능하다.
- 웹 사이트 사용자가 HTML 문서에 작성된 콘텐츠를 잘 이해할 수 있도록 돕는 역할을 한다.
주의!: CSS는 UI(사용자 인터페이스)를 고려해야한다!
...
그렇다면 UI는 무엇일까?
인터페이스는 컴퓨터와 교류하기 위한 연결고리!
메세지를 키보드 인터페이스로 입력하고, 마우스 모양 인터페이스를 사용할 수 있는 것처럼 사용자가 쉽게 사용할 수 있는 인터페이스는 앞에 ‘사용자’를 붙여 사용자인터페이스, 즉 UI라고 부름
FE는 웹 개발 기술을 기반으로 사용자와 소통할 수 있는 웹 페이지 제작을 담당한다. 그렇기 때문에 애플리케이션과 소통이 필요한 UI 제작은 FE 개발자의 기본 소양이다.
CSS를 잘 이용해 본텐츠가 더욱 잘 보이게 레이아웃을 적절히 디자인하는 것이 필요
- 아무리 훌륭한 내부 기능을 갖고 있더라도, UI가 없으면 소용 X
- 사용자가 애플리케이션을 사용하게 하려면 UI가 꼭 필요!
이처럼 중요한 UI를 만드는 것이 프론트엔드 개발자의 역할이다!
그럼 이제 UI의 중요성을 알았으니, CSS 내용에 대해 알아보자!
CSS에는 id와 class가 있는데, 그 둘의 차이점을 표로 보자.
id와 class의 차이점
id | class |
---|---|
#으로 선택 | .으로 선택 |
한 문서에 단 하나의 요소에만 적용 | 동일한 값을 갖는 요소 많음 |
특정 요소에 이름을 붙이는 데 사용 | 스타일의 분류(classification)에 사용 |
흠... id랑 class로 구분하는건 알겠어! 그럼 다른 요소를 바꿀 때는 어떻게 할까?
만약...글자 색이나 글꼴을 바꾸고 싶을때 어떻게 하지? 정렬은...?
.red {
color: #ff0000;
}
.box {
color: #155724; /* 글자 색상 */
background-color: #d4edda; /* 배경 색상 */
border-color: #c3e6cb; /* 테두리 색상 */
}
.emphasize {
font-family: "SF Pro KR", "MalgunGothic", "Verdana";
}
h1{
font: 12px/1em "SF Pro KR" #ff0;
}
.title {
font-size: 24px;
}
font-weight
text-decoration
letter-spacing
line-height
text-align
, 유효한 값으로는 left
, right
, center
, justify
(양쪽 정렬)vertical-align
속성을 쉽게 떠올릴 수 있지만, 이 속성은 부모 요소의 display
속성이 반드시 table-cell
이어야 하기 때문이다. 어라...? 그럼 글꼴 사이즈는 px 하나만 쓰나? 그거 말고 다른 단위가 있나?
...있다! 바로 글꼴에 따르냐 화면에 따르냐 정할때 말이다!
px
사용한다.rem
을 추천(root의 글자 크기)em
은 부모 엘리먼트에 따라 상대적으로 크기가 변경되므로 계산이 어려운데 rem
은 root의 글자 크기에 따라서만 상대적으로 변한다)반응형 웹(responsive web)에서 기준점을 만들 때
px
로 정함화면 너비나 높이에 따른 상대적인 크기가 중요한 경우
vw
, vh
를 사용(웹사이트의 보이는 영역을 Viewport라고 함)vw
, vh
는 각각 viewport width와 viewport height를 뜻하며, 1vw
는 보이는 영역 너비의 1/100, 1vh
는 보이는 영역 높이의 1/100100vw
, 100vh
를 사용해 구현한다.우와 생각보다 고려해야 할게 많네...? CSS는 생각보다 복잡하네...
맞다. CSS는 깊게 파고들면 파고들수록 어렵다.
그 이유로 모든 콘텐츠는 고유한 영역이 있는데, 그것을 하나하나 지정하고 특성을 고려해서 스타일을 하려니 어려운 것이다...!
예를 들어 박스모델을 한 번 알아보자.
박스 모델은 두가지로 나눌 수 있다
- 줄 바꿈이 되는 박스는 block 박스
- 줄 바꿈이 일어나지 않고, 크기 지정을 할 수 없는 박스는 inline 박스
- 줄 바꿈이 일어나지 않는 동시에 block 박스의 특징을 가지는 inline-block 박스
- 줄 바꿈이 되는 요소:
<h1>
,<p>
- 줄 바꿈이 되지 않는 요소:
<span>
더 많은 block 요소의 목록은 MDN block 엘리먼트 목록, inline 요소의 목록은 inline 엘리먼트 목록을 찾아보자!
- block 요소의 대표적인 예는
<div>
,<p>
- inline 요소의 대표적인 예는
<span>
- inline-block 박스는 inline 박스처럼 다른 요소의 옆으로 붙으면서, 자체적으로 고유의 크기를 가진다.
span {
background: yellow;
display: inline-block;
width: 100px;
height: 100px;
}
표로 간단히 세가지를 비교해보자!
아! 박스요소는 3가지로 나뉠 수 있구나... 그렇다면...박스를 구성하는 요소로 무엇이 있을까?
- border 속성에 적용된 각각의 값은 테두리 두께(
border-width
), 테두리 스타일(border-style
), 테두리 색상(border-color
)
p {
border: 1px solid red;
}
- 각각의 값은 top, right, bottom, left로 시계방향(상우하좌)
p {
margin: 10px 20px 30px 40px;
padding: 10px 20px 30px 40px;
}
/* 값을 두 개만 넣으면 top과 bottom이 10px, left 및 right가 20px */
p {
margin: 10px 20px;
}
/* 값을 하나만 넣으면 모든 방향의 바깥 여백에 적용 */
p {
margin: 10px;
}
/* 음수도 사용 가능-> 화면 밖에서 사라지거나 겹치게 만들 수 있음 */
p {
margin-top: -2rem;
}
- 박스의
height
속성에 콘텐츠가 차지하는 공간보다 작은 값을 지정할 때, 콘텐츠가 박스를 뚫고 나가는 경우에는 박스 크기에 맞게 콘텐츠를 더 이상 표시하지 않거나, 혹은 박스 안에 스크롤을 추가하여 콘텐츠를 확인할 수 있게 만든다.
p {
height: 40px;
overflow: auto;
}
overflow: hidden; overflow-x, overflow-y 도 사용 가능하다
여백과 테두리 두께를 포함해서 박스 크기를 계산
- 모든 요소에
box-sizing: border-box
를 적용하면, 모든 박스에서 여백과 테두리를 포함한 크기로 계산한다.- 일반적으로
box-sizing
은 HTML 문서 전체에 적용한다.box-sizing
을 일부 요소에만 적용하는 경우, 혼란을 가중시킬 수 있다.content-box
는 박스의 크기를 측정하는 기본값. 그러나 대부분의 레이아웃 디자인에서 여백과 테두리를 포함하는 박스 크기 계산법인border-box
를 권장한다.
* {
box-sizing: border-box;
}
우와! 이렇게나 다양하다니... 신기하다! 아! 그럼 마지막으로 셀렉터를 한 번 알아볼까?
/* 전체 셀렉터 */
* { }
/* 태그 셀렉터 -> 복수 선택 가능*/
h1 { }
div { }
section, h1 { }
/* ID 셀렉터 */
#only { }
/* class 셀렉터 */
.widget { }
.center { }
/* attribute 셀렉터 */
a[href] { } /*태그[속성명] 속성명이 있는 항목*/
p[id="only"] { } /*태그 [속성명="속성값"] 속성명에 속성값과 일치하는 항목*/
p[class~="out"] { } /*태그[속성명~="속성값"] 속성값에 공백이 있는 경우 그 중 하나라도 일치하는 항목 or 공백이 없으면 정확히 일치하는 속성값이 있는 항목*/
p[class|="out"] { } /* 태그[속성명|="속성값"] 속성값에 하이픈(-)이 있는 경우 속성값으로 시작하는 항목 or 하이픈(-)이 없으면 정확히 일치하는 값이 있는 항목 */
section[id^="sect"] { } /* 태그[속성명^="속성값"] 속성값으로 시작하는 항목 */
div[class$="2"] { } /*태그[속성명$="속성값"] 속성값으로 끝나는 항목*/
div[class*="w"] { } /* 태그[속성명*="속성값"] 속성값을 포함하는 항목*/
/* 전체 셀렉터 */
* { }
/* 태그 셀렉터 -> 복수 선택 가능*/
h1 { }
div { }
section, h1 { }
/* ID 셀렉터 */
#only { }
/* class 셀렉터 */
.widget { }
.center { }
/* attribute 셀렉터 */
a[href] { } /*태그[속성명] 속성명이 있는 항목*/
p[id="only"] { } /*태그 [속성명="속성값"] 속성명에 속성값과 일치하는 항목*/
p[class~="out"] { } /*태그[속성명~="속성값"] 속성값에 공백이 있는 경우 그 중 하나라도 일치하는 항목 or 공백이 없으면 정확히 일치하는 속성값이 있는 항목*/
p[class|="out"] { } /* 태그[속성명|="속성값"] 속성값에 하이픈(-)이 있는 경우 속성값으로 시작하는 항목 or 하이픈(-)이 없으면 정확히 일치하는 값이 있는 항목 */
section[id^="sect"] { } /* 태그[속성명^="속성값"] 속성값으로 시작하는 항목 */
div[class$="2"] { } /*태그[속성명$="속성값"] 속성값으로 끝나는 항목*/
div[class*="w"] { } /* 태그[속성명*="속성값"] 속성값을 포함하는 항목*/
- 첫 번째로 입력한 요소의 바로 아래 자식인 요소를 선택한다.
- 아래 예시의 경우
<header>
요소 바로 아래에 있는 두 개의<p>
요소는 선택되지만,<span>``header p {}``header p {}
요소의 자식인<p>
요소는 선택되지 않는다.
header > p { }
<header>
<p> <!-- 선택 -->
<span>
<p></p>
</span>
</p>
<p> <!-- 선택 -->
<span>
<p></p>
</span>
</p>
</header>
- 첫 번째로 입력한 요소의 후손을 선택한다.
- 아래 예시의 경우
<header>
요소의 자식인<p>
요소 뿐 아니라,<header>
요소의 자식인<p>
요소까지 모두 선택한다.
header p {}
<header>
<p><!-- 선택 -->
<span>
<p><!-- !!선택!! -->
</p>
</span>
</p>
<p><!-- 선택 -->
<span>
<p><!-- !!선택!! -->
</p>
</span>
</p>
</header>
- 같은 부모 요소를 공유하면서, 첫 번째 입력한 요소 뒤에 오는 두 번째 입력한 요소를 모두 선택한다.
- 아래 예시의 경우
<section>
요소 뒤에 있는 세 개의<p>``section ~ p { }
요소를 모두 선택한다.
section ~ p { }
<header>
<section></section>
<p></p> <!-- 선택 -->
<p></p> <!-- 선택 -->
<p></p> <!-- 선택 -->
</header>
- 같은 부모 요소를 공유하면서, 첫 번째 입력한 요소 바로 뒤에 오는 두 번째 입력한 요소를 선택한다
- 예시의 경우
<section>
요소 뒤에 있는 세 개의<p>
요소 중 첫 번째<p>
요소를 선택한다.
section + p { }
<header>
<section></section>
<p></p> <!-- 선택 -->
<p></p>
<p></p>
</header>
가상 클래스는 요소의 상태 정보에 기반해 요소를 선택한다
a:link { } /*사용자가 방문하지 않은 <a>요소를 선택합니다.*/
a:visited { } /*사용자가 방문한 <a>요소를 선택합니다. */
a:hover { } /* 마우스를 요소 위에 올렸을 때 선택합니다. */
a:active { } /* 활성화 된(클릭된) 상태일 때 선택합니다. */
a:focus { } /* 포커스가 들어와 있을 때 선택합니다. */
input:checked + span { } /*체크 상태일 때 선택합니다. */
input:enabled + span { } /*사용 가능한 상태일 때 선택합니다. */
input:disabled + span { } /*사용 불가능한 상태일 때 선택합니다. */
p:first-child { }
ul > li:last-child { }
ul > li:nth-child(2n) { }
section > p:nth-child(2n+1) { }
ul > li:first-child { }
li:last-child { }
div > div:nth-child(4) { }
div:nth-last-child(2) { }
section > p:nth-last-child(2n + 1) { }
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 { }