CSS하는데 내가 원하는 그 위치에 안 있어서 부스트코스 강의를 듣고 정리한 내용.
웹 페이지를 사람에 비유해보자면 마크업 언어(HTML)는 몸의 구조(뻐, 근육)를 담당하고 CSS는 옷, 신발과 같이 외적으로 꾸며주는 역할을 한다고 보면 된다.
Cascading Style Sheet
CSS는 HTML 요소를 꾸며주는 역할을 한다. CSS는 꾸밀 대상이 되는 요소와 그에 대한 스타일 내용으로 이루어져 있다.
CSS 문법과 적용
CSS 구문
h1 { color:yellow;font-size:2em; }
- 선택자(selector):
h1
- 속성(property):
color
- 값(value):
yellow
- 선언(declaration):
color: yellow, font-size: 2em
- 선언부(declaration block):
{ color: yellow; font-size:2em; }
- 규칙(rule set):
h1 { color: yellow; font-size:2em; }
CSS 파일은 여러 개의 규칙으로 이루어져 있고, 선택자와 선언부 사이, 선언과 선언 사이는 앞뒤로 개행을 해도 상관이 없다. 그러나 속성 이름과 속성값 사이에는 개행을 하면 안 된다.
CSS의 속성(Property)과 HTML의 속성(Attribute)
CSS 주석
/* 주석 내용 */
/*
주석은 여러 줄로도
선언 가능
*/
CSS의 적용
CSS와 문서를 연결하는 방법은 네 가지가 있다.
Inline
- 해당 요소에 직접 스타일 속성을 이용해 규칙을 선언하는 방법
- 해당 요소에 직접 입력하기 때문에 선택자는 필요하지 않게 되고, 선언부에 내용만 스타일 속성의 값으로 넣어준다.
- 코드의 재활용이 되지 않기 때문에 자주 사용하지 않음
<div style="color:red;">내용</div>
Internal
- 문서에
<style>
을 사용하는 방법 <style>
은<head>
내부에 들어가며<style>
안에 스타일 규칙이 들어감<style> div {color: red;} </style>
- 많은 페이지가 있는 경우에는 모든 페이지에 저마다의 규칙을 선언해줘야 하는데, 페이지가 많고 스타일 규칙 내용이 많아지면 한계가 있음
External
- 외부 스타일 시트 파일을 이용한 방법
- 외부 스타일 시트란 스타일 규칙들을 별도의 외부 파일로 만들어 넣는 방식을 말한다.
- 외부 파일은 확장자가 .css이며 css 파일이라 부름
div{color:red;}
우선 CSS 파일을 하나 만들고 스타일 규칙을 선언한 후,
<link>
태그를 사용해 CSS 파일을 연결한다.<link rel="stylesheet" href="css/style,css">
<head>
내부에<link>
를 선언한 후href
속성을 이용해 CSS 파일의 경로를 적는다.rel
속성은 연결되는 파일이 문서와 어떤 관계인지를 명시하는 속성으로, CSS 파일은stylesheet
라고 적어야 함.외부 스타일 시트 방식으로 스타일을 선언하면 많은 페이지가 있더라도 이 한 줄로 모든 페이지에 같은 스타일을 적용할 수 있고, 수정이 필요할 때도 CSS 파일을 수정하면 연결된 모든 페이지에 반영할 수 있다. 또한 파일 관리가 편하면서도 용량이 작기 때문에 주로 사용되는 방법이다.
Import
- 스타일 시트 내에서 다른 스타일 파일을 불러오는 방식
@import url("css/style.css");
<style>
내부 상단이나 외부 스타일 시트 파일 상단에 선언하는데, 성능이 좋지 않아 거의 안 씀.
Selector
요소 선택자
선택자 중에 가장 기본이 되는 선택자. 태그 선택자라고도 부름
요소 선택자는 위 코드처럼 선택자 부분에 태그 이름이 들어가고, 문서 내에 선택자에 대항하는 모든 요소에 스타일 규칙이 적용된다.
h1 { color: yellow; }
h2 { color: yellow; }
h3 { color: yellow; }
h4 { color: yellow; }
h5 { color: yellow; }
h6 { color: yellow; }
전체 선택자라는 것도 있는데, *
기호로 문서 내의 모든 요소를 선택할 수 있다. 이렇게 선언하면 한 번의 선언만으로 문서 내의 모든 요소에 스타일 규칙을 적용할 수 있지만, 성능이 좋지 않으므로 전체 선택자 사용은 지양하도록 하자.
*{color:yellow;}
선택자 뿐만 아니라 선언들도 그룹화할 수 있으며, 선택자와 선언을 동시에 그룹화할 수도 있다.
h1 { color: yellow; font-size: 2em; background-color: gray; }
h1, h2, h3, h4, h5, h6 { color: yellow; font-size: 2em; background-color: gray; }
class 선택자
- class 선택자를 사용하기 위해서는 HTML을 수정해 class 속성을 추가해야 한다.
- class 속성은 글로벌 속성이므로 어느 태그에서도 사용할 수 있다.
- class 속성에 값을 넣게 되면, class 선택자를 사용해 해당 요소에 스타일 규칙을 적용할 수 있다.
- 클래스 이름 앞에
.
을 붙여 클래스 선택자를 사용한다.
.foo{font-size:30px;}
<p class="foo"> ... </p>
위 코드처럼 <p>
의 class 속성 값으로 foo라는 값을 넣었다면, CSS에서 그 값(“foo”)을 선택자로 지정하면 된다. 그러면 어느 요소든지 class 속성값이 “foo”로 선언된 요소가 있다면 해당 스타일 규칙을 적용받게 된다.
다중 class
class 속성은 꼭 하나의 값만 가질 수 있는 것은 아니고, 공백으로 구분하여 여러 개의 class 값을 넣을 수 있다.
.foo { font-size: 30px; }
.bar { color: blue; }
<p class="foo bar"> ... </p>
id 선택자
class 선택자와 비슷하나 선택자를 쓸 때 .
기호 대신 #
기호를 사용하고, 요소에는 class 속성 대신 id 속성을 사용한다.
#bar { background-color: yellow; }
<p id="bar"> ... </p>
class 선택자와의 차이점
- .기호가 아닌 #기호 사용
- 태그의 class 속성이 아닌 id 속성을 참조
- 문서 내에 유일한 요소에 사용
- 구체성
가장 큰 차이점은 class와 달리 id는 문서 내에서 유일해야 한다는 점이다. 클래스 선택자는 여러 요소에 같은 클래스를 넣고 같은 규칙을 적용 할 수 있지만, id 속성값은 문서 내에 유일하게 사용돼야 한다.
선택자의 조합
- 요소와 클래스를 조합한 경우
<p>
이면서 class 속성에 bar가 있어야 적용됨/* 요소와 class의 조합 */ p.bar { ... }
- 다중 클래스
class 속성에 foo와 bar가 모두 있어야 적용됨
/* 다중 class */ .foo.bar { ... }
- id와 class를 조합힌 경우
id가 foo이며 class가 bar인 요소에 적용됨
/* id와 class의 조합 */ #foo.bar { ... }
속성 선택자
단순 속성으로 선택
p[class] { color: silver; }
p[class][id] { text-decoration: underline; }
<p class="foo">Hello</p>
<p class="bar">CSS</p>
<p class="baz" id="title">HTML</p>
속성 선택자는 대괄호를 이용해 선언하며 대괄호 안에 속성 이름이 들어간다.
p[class]
선택자의 규칙은 class 속성만 존재하면 적용이 되기 때문에 3가지 요소 모두에 적용되지만, p[class][id]
선택자의 규칙은 class 속성과 id 속성 모두 있는 요소만 해당하기 때문에 마지막 요소에만 적용된다.
정확한 속성값으로 선택
정확한 속성값으로 선택은 제목 그대로 속성의 값으로 요소를 선택한다. 선택자는 대괄호 안에 속성 이름과 속성값을 다 적으면 됨
p[class="foo"] { color: silver; }
p[id="title"] { text-decoration: underline; }
p[class="foo"]
는 <p>
이면서 class 속성의 값이 foo이면 적용되고, p[id="title"]
는 <p>
이면서 id 속성의 값이 title이면 적용된다.
부분 속성값으로 선택
[class~="bar"]
: class 속성의 값이 공백으로 구분한 “bar” 단어가 포함되는 요소 선택[class^="bar"]
: class 속성의 값이 “bar”로 시작하는 요소 선택[class$="bar"]
: class 속성의 값이 “bar”로 끝나는 요소 선택[class*="bar"]
: class 속성의 값이 “bar” 문자가 포함되는 요소 선택
<p class="color hot">red</p>
<p class="cool color">blue</p>
<p class="colorful nature">rainbow</p>
p[class~="color"] { font-style: italic; }
p[class^="color"] { font-style: italic; }
p[class$="color"] { font-style: italic; }
p[class*="color"] { font-style: italic; }
p[class~="color"] { font-style: italic; } /* 1, 2번째 요소 */
p[class^="color"] { font-style: italic; } /* 1, 3번째 요소 */
p[class$="color"] { font-style: italic; } /* 2번째 요소 */
p[class*="color"] { font-style: italic; } /* 1, 2, 3번째 요소 */
문서 구조 관련 선택자
선택자 중에는 문서의 구조를 이용하여 요소를 선택하는 선택자도 있다. 문맥이나 요소의 구조를 기반으로 하여 선택자를 조합하는 것을 “조합자” 또는 “결정자” 라고 부르는데, 조합자를 이용하면 문서 구조를 이용해 좀 더 유연하게 요소를 선택하고 스타일을 적용할 수 있다.
문서 구조의 이해
다음 HTML 코드에서 각 요소들에 대해 부모와 자식, 조상과 자손, 그리고 형제의 관계를 살펴보자.
<html>
<body>
<div>
<h1><span>HTML</span>: Hyper Text Markup Language</h1>
</div>
<p>HTML과 CSS와 JAVASCRIPT를 이용해서 멋진 웹 사이트를 제작할 수 있습니다.</p>
</body>
</html>
부모와 자식
부모 요소는 그 요소를 포함하는 가장 가까운 상위 요소로, 그 요소의 부모 요소는 단 하나뿐이다.
자식 요소는 부모 요소와 반대라고 생각하면 되며 자식 요소는 여러 개일 수 있다.
<body>
의 부모 요소:<html>
↔<html>
의 자식 요소:<body>
,<div>
,<h1>
,<span>
,<p>
<div>
의 조상 요소:<html>
,<body>
↔<body>
의 자손 요소:<div>
,<h1>
,<span>
,<p>
<h1>
의 조상 요소:<html>
,<body>
,<div>
↔<div>
의 자손 요소:<h1>
,<span>
<span>
의 조상 요소:<html>
,<body>
,<div>
,<h1>
↔<h1>
의 자손 요소:<span>
<p>
의 조상 요소:<html>
,<body>
↔<body>
의 자손 요소:<div>
,<h1>
,<span>
,<p>
형제
같은 부모를 가지고 있는 요소들은 서로 형제 관계에 있다. 위 코드에서는 <div>
, <p>
가 형제 요소임.
형제 관계 중에는 인접한 관계도 있는데, 형제 관계에 있는 요소 중 바로 뒤에 이어 나오는 요소를 인접해 있다고 한다. 문서의 구조는 흔히 가계도나 조직도의 관계와 비슷하다고 생각하면 이해하기 쉽다.
문서 구조 관련 선택자
문서 구조를 이용한 선택자는 자손 선택자와 자식 선택자 그리고 인접 선택자 세 가지가 있다.
자손 선택자
선택자 사이에 아무 기호 없이 그냥 공백으로 구분한다.
/* <div>의 자손 요소인 <span>를 선택하는 선택자 */
div span { color: red; }
자식 선택자
선택자 사이에 닫는 꺽쇠 기호(>)를 넣는다. 꺽쇠 기호와 선택자 기호 사이에는 공백은 있거나 없어도 상관이 없다.
/* <div>의 자식 요소인 <h1>를 선택하는 선택자 */
div > h1 { color: red; }
인접 형제 선택자
형제 관계이면서 바로 뒤에 인접해 있는 요소를 선택하는 선택자. 선택자 사이에 + 기호를 넣는다(공백은 있거나 없어도 상관 없음).
div + p { color: red; }
가상 선택자
Pseudo Class (가상 클래스)
- 미리 정의해놓은 상황에 적용되도록 약속된 보이지 않는 클래스
- 개발자가 직접 요소에 클래스를 선언하는 것은 아니고, 약속된 상황이 되면 브라우저 스스로 클래스를 적용해준다.
- :(콜론) 기호를 써서 나타낸다.
예를 들어 <p>
에 마우스 커서를 올렸을 때만 특정 스타일을 주고 싶다고 한다면 어떻게 해야 할까?
가상 클래스가 없다면 이런 과정을 거쳐야 한다.
- 임의의 클래스 선택자를 선언하여 특정 스타일 규칙을 만든다.
- p 요소에 커서가 올라가면 p 요소에 클래스를 집어넣는다.
- p 요소에서 커서가 빠지면 p 요소에 클래스를 삭제한다.
여기서 2, 3번은 동적으로 변화되어야 하는데, HTML과 CSS는 정적인 언어이기 때문에 처리할 수 없다. 그래서 CSS에서는 흔하게 사용되는 여러 패턴에 대해서 미리 정의해놓고, 가상 클래스로 제어할 수 있도록 한다.
:pseudo-class {
property: value;
}
문서 구조와 관련된 가상 클래스
문서 구조와 관련된 가상 클래스는 first-child와 last-child 가상 클래스 선택자이다.
:first-child
: 첫 번째 자식 요소 선택:last-child
: 마지막 자식 요소 선택
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
</ul>
li:first-child { color: red; }
li:last-child { color: blue; }
위 코드에서는 첫 번째 <li>
와 마지막 <li>
에 가상 클래스가 적용된다. 그래서 실제 <li>
에는 class 속성이 없지만 내부적으로 가상 클래스가 적용되어 마치 아래의 코드와 같이 동작한다.
<ul>
<li class="first-child">HTML</li>
<li>CSS</li>
<li class="last-child">JS</li>
</ul>
앵커 요소와 관련된 가상 클래스
앵커 요소와 관련된 가상 클래스로는 :link와 :visited가 있다.
:link
: 하이퍼 링크이면서 아직 방문하지 않은 앵커:visited
: 이미 방문한 하이퍼링크를 의미 하이퍼 링크는 앵커 요소에 href 속성이 있는 것을 의미한다.
a:link { color: blue; }
a:visited { color: gray; }
사용자 동작과 관련된 가상 클래스
이 클래스들도 <a>
에 주로 많이 쓰이지만 <a>
에만 쓸 수 있는 것은 아니며, 이 조건에 맞는 상황이 되는 요소들은 다 사용이 가능하다.
:focus
: 현재 입력 초점을 가진 요소에 적용:hover
: 마우스 포인터가 있는 요소에 적용:active
: 사용자 입력으로 활성화된 요소에 적용
a:focus { background-color: yellow; }
a:hover { font-weight: bold; }
a:active { color: red; }
:focus
는 현재 입력 초점을 가진 요소에 적용되며, 지금 현재 선택을 받는 것을 의미한다. 예를 들어 입력 폼 요소에 텍스트를 입력하려고 마우스 클릭해서 커서를 입력 폼 위에 올려놓으면 그때 입력 폼 요소가 초점을 받는 상태가 되며, 또 키보드의 탭 키를 이용해서 요소를 탐색하다 보면 링크나 버튼에 점선 테두리가 이동하는 것을 볼 수 있는데, 점선 테두리가 위치하는 것도 초점을 받은 상태이다.
:hover
는 마우스 커서가 있는 요소에 적용된다. (마우스를 올렸을 때를 의미)
:active
는 사용자 입력으로 활성화된 요소를 의미하는데, <a>
를 클릭할 때 또는 <button>
를 눌렀을 때처럼 순간적으로 활성화된다.
Pseudo Element (가상 요소)
- 가상 요소는 HTML 코드에 존재하지 않는 구조 요소에 스타일 부여할 수 있음
- 선언 방법은 가상 클래스처럼 콜론 사용
::pseudo-element { property: value; }
:before
: 가장 앞에 요소를 삽입:after
: 가장 뒤에 요소를 삽입:first-line
: 요소의 첫 번째 줄에 있는 텍스트:first-letter
: 블록 레벨 요소의 첫 번째 문자
예제
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
p::before { content: "###" }
p::after { content: "!!!" }
p::first-line { ... }
p::first-letter { ... }
before와 after 가상 요소는 애초에 내용이 없는 상태로 생성되기 때문에 내용을 넣기 위해 content 속성을 이용해야 한다.
실제 HTML 코드에는 나타나지 않지만, before와 after가 어떻게 동작하는지 이해를 돕기 위해 코드를 아래와 같이 변경해보자.
<p>
<before>###</before>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
<after>!!!</after>
</p>
눈에 보이지 않지만, 내부에서 이처럼 요소가 생성된다. first-line과 first-letter도 마찬가지로 아래 코드와 같은 것으로 생각하면 됨.
<p>
<first-letter>L</first-letter>orem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<p>
<!-- 모니터 가로 해상도에 따라 요소가 포함하는 내용 변동 -->
<first-line>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiu ..(..어딘가쯤..) </first-line>... unt ut labore et dolore magna aliqua.
</p>
구체성
어떤 규칙이 우선으로 적용되어야 하는지에 대해 정해진 규칙. 구체성은 선택자를 얼마나 명시적으로(구체적으로) 선언했느냐를 수치화한 것으로, 구체성의 값이 클수록 우선으로 적용된다.
0, 0, 0, 0
구체성은 4개의 숫자 값으로 이루어져 있으며, 값을 비교할 때는 좌측에 있는 값부터 비교하고 좌측 부분의 숫자가 클수록 높은 구체성을 갖는다.
구체성은 아래의 규칙대로 계산된다.
- 0, 1, 0, 0 : 선택자에 있는 모든 id 속성값
- 0, 0, 1, 0 : 선택자에 있는 모든 class 속성값, 기타 속성, 가상 클래스
- 0, 0, 0, 1 : 선택자에 있는 모든 요소, 가상 요소
- 전체 선택자는 0, 0, 0, 0을 가진다.
- 조합자는 구체성에 영향을 주지 않는다. (>, + 등)
h1 { ... } /* 0,0,0,1 */
body h1 { ... } /* 0,0,0,2 */
.grape { ... } /* 0,0,1,0 */
*.bright { ... } /* 0,0,1,0 */
p.bright em.dark { ... } /* 0,0,2,2 */
#page { ... } /* 0,1,0,0 */
div#page { ... } /* 0,1,0,1 */
인라인 스타일
인라인 스타일로 선언된 경우는 어떨까?
p#page { color: red; }
<p id="page" style="color:blue">Lorem impusm dolor sit.</p>
첫 번째는 0, 1, 0, 1의 구체성을 가지는 선택자로 스타일을 선언했고, 두 번째는 요소에 직접 인라인 스타일 방식으로 스타일을 선언했는데, 결과적으로 <p>
에는 color: blue가 적용된다. 이는 인라인 스타일의 구체성 값은 1, 0, 0, 0이며 규칙들 중 가장 큰 구체성을 갖기 때문이다.
Important
Important 키워드는 별도의 구체성 값은 없지만, 모든 구체성을 무시하고 우선권을 갖는다. important 키워드는 속성값 뒤 한 칸 공백을 주고 느낌표 기호와 함께 쓴다.
p#page { color: red !important; }
<p id="page" style="color:blue">Lorem impusm dolor sit.</p>
위의 <p>
에는 important로 인해 color: red가 적용된다.
상속
상속되는 속성
h1 { color: gray; }
<h1>Hello, <em>CSS</em></h1>
위 코드에서 <em>
은 부모인 <h1>
의 color: gray를 상속받는다. 모든 속성이 다 상속되는 것은 아니다. 일단은 margin, padding, background, border 등 박스 모델 속성들은 상속되지 않는다는 것을 알고 있도록 하자.
상속되는 속성의 구체성
* { color: red; }
h1#page { color: gray; }
<h1 id="page">Hello, <em>CSS</em></h1>
위 코드에서는 전체 선택자를 이용해 color: red를 적용하고 id 선택자를 이용해 color: gray를 선언하였다. 이때 전체 선택자의 구체성은 0, 0, 0, 0 이며 id 선택자의 구체성은 0,1,0,1 이다. 그렇다면 <em>
에는 어떤 color가 적용될까?
color: red가 적용되는데 그 이유는 바로 상속된 속성은 아무런 구체성을 가지지 못하기 때문이다.
Cascading
cascading은 스타일 규칙들이 어떠한 기준으로 요소에 적용되는지를 정한 규칙이다. cascading은 폭포가 내려오는 모양처럼 단계적인이라는 의미를 지니며, 모든 스타일 규칙들은 cascading의 단계적인 규칙에 따라 요소에 적용된다.
cascading 규칙
- 중요도(!important)와 출처(CSS 출처)
- 구체성
- 선언 순서
출처란 CSS 출처를 의미한다. CSS 출처는 제작자와 사용자, 그리고 사용자 에이전트(user agent) 경우로 구분하는데, 제작자의 경우는 사이트를 실제 제작하는 개발자가 작성한 CSS를 의미하며(대부분이 여기에 해당) 사용자의 경우는 웹 페이지를 방문하는 일반 사용자들이 작성한 CSS를, 그리고 사용자 에이전트의 경우는 일반 사용자의 환경, 즉 브라우저에 내장된 CSS를 의미한다.
스타일이 적용되는 방식은 생각보다 간단한데, 모든 스타일은 아래의 규칙에 따라 단계적으로 적용된다.
- 스타일 규칙들을 모아서 중요도가 명시적으로 선언되었는지에 따라 분류한다.
- 중요도가 명시적으로 선언된 규칙들은 그렇지 않은 규칙들보다 우선한다.
- 중요도가 있는 규칙들끼리는 아래 다른 규칙들을 적용받는다.
- 스타일 규칙들을 출처에 따라 분류한다.
- 제작자 스타일 규칙이 사용자 에이전트 스타일 규칙보다 우선한다.
- 스타일 규칙들을 구체성에 따라 분류한다.
- 구체성이 높은 규칙들이 우선한다.
- 스타일 규칙들을 선언 순서에 따라 분류합니다.
- 뒤에 선언된 규칙일수록 우선합니다.
<p id="bright">Hello, CSS</p>
p#bright { color: silver; }
p { color: red; }
위의 경우에는 구체성에 따라 color: silver가 적용된다.
p { color: silver; }
p { color: red; }
위의 경우에는 선언 순서에 따라 color: red가 적용된다.