CSS 는 HTML요소
의 style(design, layout etc)을 정의하는데 사용된다.이를 위해서 선행되어야하는 것은 스타일을 적용하고자 하는 HTML 요소를 선택
할 수 있어야 한다. 셀렉터
는 스타일을 적용하고자 하는 HTML요소
를 선택하기 위해 CSS에서 제공하는 수단이다.
위와 같은 구문을 Rule Set
이라 하며 셀렉터
에 의해 선택된 특정 HTML요소
를 어떻게 렌더링
할 것인지 브라우저에 지시하는 역할을 한다. 위의 CSS Rule set은 HTML문서
에 속해 있는 셀렉터
를 통해 모든 h1 요소 를 선택
한 후 선택된 h1 요소의 스타일을 선언 블록에서 정의하고 있다. 이와 같은 Rule Set의 집합을 스타일시트(Style Sheet)
라 한다.
셀렉터
로 HTML요소
를 선택하고 {}
내에 프로퍼티(속성)
와 값
을 지정하는 것으로 다양한 style을 정의
할 수 있다. 프로퍼티는 표준 스펙으로 이미 지정되어 있는 것을 사용하여야하며 사용자가 임의로 정의할 수 없다. 여러 개의 프로퍼티를 연속해서 지정할 수 있으며 세미콜론(;)
으로 구분한다.
p {
color: ...;
font-size: ...;
}
셀렉터
로 지정한 HTML요소
에 style을 적용하기 위해 프로퍼티를 사용했다. 프로퍼티의 값은 해당 프로퍼티에 사용할 수 있는 값을 키워드
크기 단위
색상 표현 단위
등의 특정 단위
로 지정하여야 한다.
p {
color: orange;
font-size: 16px;
}
HTML 은 CSS 를 포함할 수 있다. CSS를 가지고 있지 않은 HTML은 브라우저에서 기본으로 적용하는 CSS(user agent stylesheet)에 의해 렌더링된다.
HTML에서 외부에 있는 CSS 파일을 로드하는 방식이다. 가장 일반적으로 사용된다.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>Hello World</h1>
<p>This is a web page.</p>
</body>
</html>
h1 { color: red; }
p { background: blue; }
HTML 내부에 CSS를 포함시키는 방식이다. 매우 간단한 웹페이지의 경우는 문제될 것이 없겠지만 Link style을 사용하는 편이 좋다. HTML과 CSS는 서로 역할이 다르므로 다른 파일로 구분되어 작성하고 관리되는 것이 바람직하다.
<!DOCTYPE html>
<html>
<head>
<style>
h1 { color: red; }
p { background: aqua; }
</style>
</head>
<body>
<h1>Hello World</h1>
<p>This is a web page.</p>
</body>
</html>
HTML요소의 style 프로퍼티에 CSS를 기술하는 방식이다. JavaScript가 동적으로 CSS를 생성할 때 사용하는 경우가 있다. 하지만 일반적인 경우 Link style을 사용하는 편이 좋다.
<!DOCTYPE html>
<html>
<body>
<h1 style="color: red">Hello World</h1>
<p style="background: aqua">This is a web page.</p>
</body>
</html>
모든 웹 브라우저는 디폴트 스타일(브라우저가 내장하고 있는 기본 스타일)을 가지고 있어 CSS가 없어도 작동한다. 그런데 웹브라우저에 따라 디폴트 스타일이 상이하고 지원하는 tag나 style도 제각각이어서 주의가 필요하다.Reset CSS
는 기본적인 HTML 요소의 CSS를 초기화
하는 용도로 사용한다. 즉, 브라우저 별로 제각각인 디폴트 스타일을 하나의 스타일로 통일시켜 주는 역할
을 한다.
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
CSS(Cascading Style Sheets)는 HTML 요소
의 style(design, layout etc)
을 정의한다. 그리하려면 HTML이 존재하여야 하고 또한 style을 적용하고자하는 HTML 요소를 특정
할 필요가 있다. 이러한 목적으로 사용되는 것이 셀렉터(Selector)
이다. 즉, style을 적용하고자하는 HTML 요소를 셀렉터로 특정하고 선택된 요소에 스타일을 정의하는 것이다.
<!DOCTYPE html>
<html>
<head>
<style>
h1 { color: red; }
p { color: blue; }
</style>
</head>
<body>
<h1>Hello World!</h1>
<p>This paragraph is styled with CSS.</p>
</body>
</html>
복수개의 셀렉터를 연속하여 지정할 수 있으며 쉼표( , )로 구분한다.
h1, p { color: red; }
패턴 | Description |
---|---|
* | HTML 문서 내의 모든 요소를 선택한다. html 요소를 포함한 모든 요소가 선택된다. (head 요소도 포함된다) |
<!DOCTYPE html>
<html>
<head>
<style>
/* 모든 요소를 선택 */
* { color: red; }
</style>
</head>
<body>
<h1>Heading</h1>
<div>
<p>paragraph 1</p>
<p>paragraph 2</p>
</div>
<p>paragraph 3</p>
</body>
</html>
패턴 | Description |
---|---|
태그명 | 지정된 태그명을 가지는 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* 모든 p 태그 요소를 선택 */
p { color: red; }
</style>
</head>
<body>
<h1>Heading</h1>
<div>
<p>paragraph 1</p>
<p>paragraph 2</p>
</div>
<p>paragraph 3</p>
</body>
</html>
패턴 | Description |
---|---|
#id 어트리뷰트 값 | id 어트리뷰트 값을 지정하여 일치하는 요소를 선택한다. id 어트리뷰트 값은 중복될 수 없는 유일한 값이다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* id 어트리뷰트 값이 p1인 요소를 선택 */
#p1 { color: red; }
</style>
</head>
<body>
<h1>Heading</h1>
<div class="container">
<p id="p1">paragraph 1</p>
<p id="p2">paragraph 2</p>
</div>
<p>paragraph 3</p>
</body>
</html>
패턴 | Description |
---|---|
.class 어트리뷰트 값 | class 어트리뷰트 값을 지정하여 일치하는 요소를 선택한다. class 어트리뷰트 값은 중복될 수 있다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* class 어트리뷰트 값이 container인 모든 요소를 선택 */
/* color 어트리뷰트는 자식 요소에 상속된다. */
.container { color: red; }
/* not supported in IE */
#p2 { color: initial; }
</style>
</head>
<body>
<h1>Heading</h1>
<div class="container">
<p id="p1">paragraph 1</p>
<p id="p2">paragraph 2</p>
</div>
<p>paragraph 3</p>
</body>
</html>
HTML 요소에 class 어트리뷰트 값은 공백으로 구분하여 여러 개 지정할 수 있다.
아래와 같이 클래스 셀렉터를 사용하여 미리 스타일을 정의해 두고, HTML 요소는 이미 정의되어 있는 클래스를 지정하는 것으로 필요한 스타일을 지정할 수 있다.
<!DOCTYPE html>
<html>
<head>
<style>
/* class 어트리뷰트 값이 text-center인 모든 요소를 선택 */
.text-center { text-align: center; }
/* class 어트리뷰트 값이 text-large인 모든 요소를 선택 */
.text-large { font-size: 200%; }
/* class 어트리뷰트 값이 text-red인 모든 요소를 선택 */
.text-red { color: red; }
/* class 어트리뷰트 값이 text-blue인 모든 요소를 선택 */
.text-blue { color: blue; }
</style>
</head>
<body>
<p class="text-center">Center</p>
<p class="text-large text-red">Large Red</p>
<p class="text-center text-large text-blue">Center Large Blue</p>
</body>
</html>
패턴 | Description |
---|---|
셀렉터[어트리뷰트] | 지정된 어트리뷰트를 갖는 모든 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* a 요소 중에 href 어트리뷰트를 갖는 모든 요소 */
a[href] { color: red; }
</style>
</head>
<body>
<a href="http://www.poiemaweb.com">poiemaweb.com</a><br>
<a href="http://www.google.com" target="_blank">google.com</a><br>
<a href="http://www.naver.com" target="_top">naver.com</a>
</body>
</html>
패턴 | Description |
---|---|
셀렉터[어트리뷰트=”값”] | 지정된 어트리뷰트를 가지며 지정된 값과 어트리뷰트의 값이 일치하는 모든 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* a 요소 중에 target 어트리뷰트의 값이 "_blank"인 모든 요소 */
a[target="_blank"] { color: red; }
</style>
</head>
<body>
<a href="http://www.poiemaweb.com">poiemaweb.com</a><br>
<a href="http://www.google.com" target="_blank">google.com</a><br>
<a href="http://www.naver.com" target="_top">naver.com</a>
</body>
</html>
패턴 | Description |
---|---|
셀렉터[어트리뷰트~=”값”] | 지정된 어트리뷰트의 값이 지정된 값을 (공백으로 분리된) 단어로 포함하는 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* h1 요소 중에 title 어트리뷰트 값에 "first"를 단어로 포함하는 요소 */
h1[title~="first"] { color: red; }
</style>
</head>
<body>
<h1 title="heading first">Heading first</h1>
<h1 title="heading-first">Heading-first</h1>
<h1 title="heading second">Heading second</h1>
<h1 title="heading third">Heading third</h1>
</body>
</html>
패턴 | Description |
---|---|
셀렉터[어트리뷰트 | =”값”] |
<!DOCTYPE html>
<html>
<head>
<style>
/* p 요소 중에 lang 어트리뷰트 값이 "en"과 일치하거나 "en-"로 시작하는 요소 */
p[lang|="en"] { color: red; }
</style>
</head>
<body>
<p lang="en">Hello!</p>
<p lang="en-us">Hi!</p>
<p lang="en-gb">Ello!</p>
<p lang="us">Hi!</p>
<p lang="no">Hei!</p>
</body>
</html>
패턴 | Description |
---|---|
셀렉터[어트리뷰트^=”값”] | 지정된 어트리뷰트 값으로 시작하는 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* a 요소 중에 href 어트리뷰트 값이 "https://"로 시작하는 요소 */
a[href^="https://"] { color: red; }
</style>
</head>
<body>
<a href="https://www.test.com">https://www.test.com</a><br>
<a href="http://www.test.com">http://www.test.com</a>
</body>
</html>
패턴 | Description |
---|---|
셀렉터[어트리뷰트$=”값”] | 지정된 어트리뷰트 값으로 끝나는 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* a 요소 중에 href 어트리뷰트 값이 ".html"로 끝나는 요소 */
a[href$=".html"] { color: red; }
</style>
</head>
<body>
<a href="test.html">test.html</a><br>
<a href="test.jsp">test.jsp</a>
</body>
</html>
패턴 | Description |
---|---|
셀렉터[어트리뷰트*=”값”] | 지정된 어트리뷰트 값을 포함하는 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* div 요소 중에서 class 어트리뷰트 값에 "test"를 포함하는 요소 */
div[class*="test"] { color: red; }
/* div 요소 중에서 class 어트리뷰트 값에 "test"를 단어로 포함하는 요소 */
div[class~="test"] { background-color: yellow; }
</style>
</head>
<body>
<div class="first_test">The first div element.</div>
<div class="second">The second div element.</div>
<div class="test">The third div element.</div>
<p class="test">This is some text in a paragraph.</p>
</body>
</html>
자신의 1 level 상위에 속하는 요소를 부모 요소
, 1 level 하위에 속하는 요소를 자손 요소(자식 요소)
라한다. 자신보다 n level 하위에 속하는 요소는 후손 요소(하위 요소)
라 한다. 후손 셀렉터는 셀렉터A의 모든 후손(하위) 요소 중 셀렉터B와 일치하는 요소를 선택한다.
셀렉터A 셀렉터B
<!DOCTYPE html>
<html>
<head>
<style>
/* div 요소의 후손요소 중 p 요소 */
div p { color: red; }
</style>
</head>
<body>
<h1>Heading</h1>
<div>
<p>paragraph 1</p>
<p>paragraph 2</p>
<span><p>paragraph 3</p></span>
</div>
<p>paragraph 4</p>
</body>
</html>
자손 셀렉터는 셀렉터A의 모든 자식 요소 중 셀렉터B와 일치하는 요소를 선택한다.
셀렉터A > 셀렉터B
<!DOCTYPE html>
<html>
<head>
<style>
/* div 요소의 자식요소 중 p 요소 */
div > p { color: red; }
</style>
</head>
<body>
<h1>Heading</h1>
<div>
<p>paragraph 1</p>
<p>paragraph 2</p>
<span><p>paragraph 3</p></span>
</div>
<p>paragraph 4</p>
</body>
</html>
형제(동위) 셀렉터는 형제 관계(동위 관계)
에서 뒤에 위치하는 요소를 선택할 때 사용한다.
셀렉터A의 형제 요소 중 셀렉터A 바로 뒤에 위치하는 셀렉터B 요소를 선택한다. A와 B 사이에 다른 요소가 존재하면 선택되지 않는다.
셀렉터A + 셀렉터B
<!DOCTYPE html>
<html>
<head>
<style>
/* p 요소의 형제 요소 중에 p 요소 바로 뒤에 위치하는 ul 요소를 선택한다. */
p + ul { color: red; }
</style>
</head>
<body>
<div>A div element.</div>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
<p>The first paragraph.</p>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
<h2>Another list</h2>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</body>
</html>
셀렉터A의 형제 요소 중 셀렉터A 뒤에 위치하는 셀렉터B 요소를 모두 선택한다.
셀렉터A ~ 셀렉터B
<!DOCTYPE html>
<html>
<head>
<style>
/* p 요소의 형제 요소 중에 p 요소 뒤에 위치하는 ul 요소를 모두 선택한다.*/
p ~ ul { color: red; }
</style>
</head>
<body>
<div>A div element.</div>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
<p>The first paragraph.</p>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
<h2>Another list</h2>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</body>
</html>
가상 클래스는 요소의 특정 상태에 따라 스타일을 정의할 때 사용된다.
이러한 특정 상태에는 원래 클래스가 존재하지 않지만 가상 클래스를 임의로 지정하여 선택하는 방법이다. 가상 클래스는 마침표(.)
대신 콜론(:)
을 사용한다. CSS 표준에 의해 미리 정의된 이름이 있기 때문에 임의의 이름을 사용할 수 없다.
selector:pseudo-class {
property: value;
}
<!DOCTYPE html>
<html>
<head>
<style>
/* a 요소가 hover 상태일 때 */
a:hover { color: red; }
/* input 요소가 focus 상태일 때 */
input:focus { background-color: yellow; }
</style>
</head>
<body>
<a href="#">Hover me</a><br><br>
<input type="text" placeholder="focus me">
</body>
</html>
pseudo-class | Description |
---|---|
:link | 셀렉터가 방문하지 않은 링크일 때 |
:visited | 셀렉터가 방문한 링크일 때 |
:hover | 셀렉터에 마우스가 올라와 있을 때 |
:active | 셀렉터가 클릭된 상태일 때 |
:focus | 셀렉터에 포커스가 들어와 있을 때 |
<!DOCTYPE html>
<html>
<head>
<style>
/* a 요소가 방문하지 않은 링크일 때 */
a:link { color: orange; }
/* a 요소가 방문한 링크일 때 */
a:visited { color: green; }
/* a 요소에 마우스가 올라와 있을 때 */
a:hover { font-weight: bold; }
/* a 요소가 클릭된 상태일 때 */
a:active { color: blue; }
/* text input 요소와 password input 요소에 포커스가 들어와 있을 때 */
input[type=text]:focus,
input[type=password]:focus {
color: red;
}
</style>
</head>
<body>
<a href="#" target="_blank">This is a link</a><br>
<input type="text" value="I'll be red when focused"><br>
<input type="password" value="I'll be red when focused">
</body>
</html>
pseudo-class | Description |
---|---|
:checked | 셀렉터가 체크 상태일 때 |
:enabled | 셀렉터가 사용 가능한 상태일 때 |
:disabled | 셀렉터가 사용 불가능한 상태일 때 |
<!DOCTYPE html>
<html>
<head>
<style>
/* input 요소가 사용 가능한 상태일 때,
input 요소 바로 뒤에 위치하는 인접 형제 span 요소를 선택 */
input:enabled + span {
color: blue;
}
/* input 요소가 사용 불가능한 상태일 때,
input 요소 바로 뒤에 위치하는 인접 형제 span 요소를 선택 */
input:disabled + span {
color: gray;
text-decoration: line-through;
}
/* input 요소가 체크 상태일 때,
input 요소 바로 뒤에 위치하는 인접 형제 span 요소를 선택 */
input:checked + span {
color: red;
}
</style>
</head>
<body>
<input type="radio" checked="checked" value="male" name="gender"> <span>Male</span><br>
<input type="radio" value="female" name="gender"> <span>Female</span><br>
<input type="radio" value="neuter" name="gender" disabled> <span>Neuter</span><hr>
<input type="checkbox" checked="checked" value="bicycle"> <span>I have a bicycle</span><br>
<input type="checkbox" value="car"> <span>I have a car</span><br>
<input type="checkbox" value="motorcycle" disabled> <span>I have a motorcycle</span>
</body>
</html>
pseudo-class | Description |
---|---|
:first-child | 셀렉터에 해당하는 모든 요소 중 첫번째 자식인 요소를 선택한다. |
:last-child | 셀렉터에 해당하는 모든 요소 중 마지막 자식인 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* p 요소 중에서 첫번째 자식을 선택 */
p:first-child { color: red; }
/* p 요소 중에서 마지막 자식을 선택 */
/* body 요소의 두번째 p 요소는 마지막 자식 요소가 아니다.
body 요소의 마지막 자식 요소는 div 요소이다. */
p:last-child { color: blue; }
</style>
</head>
<body>
<p>This paragraph is the first child of its parent (body).</p>
<h1>Welcome to My Homepage</h1>
<p>This paragraph is not the first child of its parent.</p>
<div>
<p>This paragraph is the first child of its parent (div).</p>
<p>This paragraph is not the first child of its parent.</p>
</div>
</body>
</html>
pseudo-class | Description |
---|---|
:nth-child(n) | 셀렉터에 해당하는 모든 요소 중 앞에서 n번째 자식인 요소를 선택한다. |
:nth-last-child(n) | 셀렉터에 해당하는 모든 요소 중 뒤에서 n번째 자식인 요소를 선택한다. |
n은 0부터 시작하는 정수이다.
n | 2n+1 | 2n-1 | 3n-2 | 3n+1 | -n+5 |
---|---|---|---|---|---|
0 | 1 | -1 | -2 | 1 | 5 |
1 | 3 | 1 | 1 | 4 | 4 |
2 | 5 | 3 | 4 | 7 | 3 |
3 | 7 | 5 | 7 | 10 | 2 |
4 | 9 | 7 | 10 | 13 | 1 |
5 | 11 | 9 | 13 | 16 | 0 |
0과 음수는 생략되기 때문에 2n+1과 2n-1, 3n-2와 3n+1은 결과적으로 같은 수열을 생성한다.
<!DOCTYPE html>
<html>
<head>
<style>
/* ol 요소의 자식 요소인 li 요소 중에서 짝수번째 요소만을 선택 */
ol > li:nth-child(2n) { color: orange; }
/* ol 요소의 자식 요소인 li 요소 중에서 홀수번째 요소만을 선택 */
ol > li:nth-child(2n+1) { color: green; }
/* ol 요소의 자식 요소인 li 요소 중에서 첫번쨰 요소만을 선택 */
ol > li:first-child { color: red; }
/* ol 요소의 자식 요소인 li 요소 중에서 마지막 요소만을 선택 */
ol > li:last-child { color: blue; }
/* ol 요소의 자식 요소인 li 요소 중에서 4번째 요소 요소만을 선택 */
ol > li:nth-child(4) { background: brown; }
/* ul 요소의 모든 자식 요소 중에서 뒤에서부터 시작하여 홀수번째 요소만을 선택 */
ul > :nth-last-child(2n+1) { color: red; }
/* ul 요소의 모든 자식 요소 중에서 뒤에서부터 시작하여 짝수번째 요소만을 선택 */
ul > :nth-last-child(2n) { color: blue; }
</style>
</head>
<body>
<ol>
<li>Espresso</li>
<li>Americano</li>
<li>Caffe Latte</li>
<li>Caffe Mocha</li>
<li>Caramel Latte</li>
<li>Cappuccino</li>
</ol>
<ul>
<li>Espresso</li>
<li>Americano</li>
<li>Caffe Latte</li>
<li>Caffe Mocha</li>
<li>Caramel Latte</li>
<li>Cappuccino</li>
</ul>
</body>
</html>
pseudo-class | Description |
---|---|
:first-of-type | 셀렉터에 해당하는 요소의 부모 요소의 자식 요소 중 첫번째 등장하는 요소를 선택한다. |
:last-of-type | 셀렉터에 해당하는 요소의 부모 요소의 자식 요소 중 마지막에 등장하는 요소를 선택한다. |
:nth-of-type(n) | 셀렉터에 해당하는 요소의 부모 요소의 자식 요소 중 앞에서 n번째에 등장하는 요소를 선택한다. |
:nth-last-of-type(n) | 셀렉터에 해당하는 요소의 부모 요소의 자식 요소 중 뒤에서 n번째에 등장하는 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* p 요소의 부모 요소의 자식 요소 중 첫번째 등장하는 p 요소 */
p:first-of-type { color: red; }
/* p 요소의 부모 요소의 자식 요소 중 마지막 등장하는 p 요소 */
p:last-of-type { color: blue; }
/* p 요소의 부모 요소의 자식 요소 중 앞에서 2번째에 등장하는 p 요소 */
p:nth-of-type(2) { color: green; }
/* p 요소의 부모 요소의 자식 요소 중 뒤에서 2번째에 등장하는 p 요소 */
p:nth-last-of-type(2) { color: orange;}
/* p 요소 중에서 첫번째 자식을 선택 */
p:first-child { background: brown;}
</style>
</head>
<body>
<h1>This is a heading</h1>
<p>The first paragraph.</p>
<p>The second paragraph.</p>
<p>The third paragraph.</p>
<p>The fourth paragraph.</p>
<div>
<h1>This is a heading</h1>
<p>The first paragraph.</p>
<p>The second paragraph.</p>
<p>The third paragraph.</p>
<p>The fourth paragraph.</p>
</div>
</body>
</html>
pseudo-class | Description |
---|---|
:not(셀렉터) | 셀렉터에 해당하지 않는 모든 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* input 요소 중에서 type 어트리뷰트의 값이 password가 아닌 요소를 선택 */
input:not([type=password]) {
background: yellow;
}
</style>
</head>
<body>
<input type="text" value="Text input">
<input type="email" value="email input">
<input type="password" value="Password input">
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
}
div {
float: left;
width: 32%;
height: 200px;
background-color: red;
/* margin-bottom: 2%; */
color: #fff;
font-size: 3em;
line-height: 200px;
text-align: center;
}
/* div 요소 중에서 1, 4, 7...번째 등장하는 요소가 아닌 요소만을 선택 */
/* 1, 4, 7... : 공차가 3인 등차수열 */
div:not(:nth-of-type(3n+1)) {
margin-left: 2%;
}
/* div 요소 중에서 4번째 이후 등장하는 요소가 아닌 요소만을 선택 */
div:not(:nth-of-type(n+4)) {
margin-bottom: 2%;
}
</style>
</head>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</body>
</html>
pseudo-class | Description |
---|---|
:valid(셀렉터) | 정합성 검증이 성공한 input 요소 또는 form 요소를 선택한다. |
:invalid(셀렉터) | 정합성 검증이 실패한 input 요소 또는 form 요소를 선택한다. |
<!DOCTYPE html>
<html>
<head>
<style>
input[type="text"]:valid {
background-color: greenyellow;
}
input[type="text"]:invalid {
background-color: red;
}
</style>
</head>
<body>
<label>입력값이 반드시 필요
<input type="text" required>
</label>
<br>
<label>특수문자를 포함하지 않는 4자리 문자 또는 숫자
<input type="text" value="ab1!"
pattern="[a-zA-Z0-9]{4}" required>
</label>
<br>
<label>핸드폰 번호 형식
<input type="text" value="010-1111-2222"
pattern="^\d{3}-\d{3,4}-\d{4}$" required>
</label>
</body>
</html>
가상 요소는 요소의 특정 부분에 스타일을 적용하기 위하여 사용된다. 특정 부분이란 예를 들어 다음과 같다.
가상 요소에는 두개의 콜론(::)을 사용한다. CSS 표준에 의해 미리 정의된 이름이 있기 때문에 임의의 이름을 사용할 수 없다.
selector::pseudo-element {
property:value;
}
pseudo-element | Description |
---|---|
::first-letter | 콘텐츠의 첫글자를 선택한다. |
::first-line | 콘텐츠의 첫줄을 선택한다. 블록 요소에만 적용할 수 있다. |
::after | 콘텐츠의 뒤에 위치하는 공간을 선택한다. 일반적으로 content 프로퍼티와 함께 사용된다. |
::before | 콘텐츠의 앞에 위치하는 공간을 선택한다. 일반적으로 content 프로퍼티와 함께 사용된다. |
::selection | 드래그한 콘텐츠를 선택한다. iOS Safari 등 일부 브라우저에서 동작 않는다. |
<!DOCTYPE html>
<html>
<head>
<style>
/* p 요소 콘텐츠의 첫글자를 선택 */
p::first-letter { font-size: 3em; }
/* p 요소 콘텐츠의 첫줄을 선택 */
p::first-line { color: red; }
/* h1 요소 콘텐츠의 앞 공간에 content 어트리뷰트 값을 삽입한다 */
h1::before {
content: " HTML!!! ";
color: blue;
}
/* h1 요소 콘텐츠의 뒷 공간에 content 어트리뷰트 값을 삽입한다 */
h1::after {
content: " CSS3!!!";
color: red;
}
/* 드래그한 콘텐츠를 선택한다 */
::selection {
color: red;
background: yellow;
}
</style>
</head>
<body>
<h1>This is a heading</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Explicabo illum sunt distinctio sed, tempore, repellat rerum et ea laborum voluptatum! Quisquam error fugiat debitis maiores officiis, tenetur ullam amet in!</p>
</body>
</html>
CSS 프로퍼티에는 키워드, 크기 단위, 색상 표현 단위 등의 특정 단위를 갖는 값을 지정한다.
각 프로퍼티에 따라 사용할 수 있는 키워드가 존재한다.예를 들어 display
의 프로퍼티의 값으로 사용할 수 있는 키워드는 block
inline
inline-block
none
이 있다.
cm, mm, inch 등의 단위도 존재하나 CSS에서 사용하는 대표적인 크기 단위는 px
em
%
이다. px은 절대값
이고 em, %는 상대값
이다. 프로퍼티 값이 0인 경우, 단위를 생략할 수 있다.
대부분 브라우저의 폰트 사이즈 기본값은 16px, 1em, 100%이다.
px
은 픽셀(화소) 단위이다. 1px은 화소 1개 크기를 의미한다.
22인치 LCD 모니터의 경우 해상도가 1680 1050 인데 이것은 가로에 1680개의 픽셀, 세로에 1050개의 픽셀을 가진다는 의미이다. 200만 화소(픽셀)의 디지털 카메라로 찍은 사진은 1600 1200 = 1,920,000으로 통상 200만 화소라 한다.
스크린에서 확대한 픽셀. 각 픽셀들은 적색(R)
녹색(G)
청색(B)
요소를 가지고 있다. 픽셀은 디바이스 해상도에 따라 상대적인 크기를 갖는다.
이와 같이 디바이스 별로 픽셀(화소)의 크기는 제각각이기 때문에 픽셀을 기준으로 하는 단위는 명확하지 않다. 따라서 대부분의 브라우저는 1px
을 1/96 인치
의 절대단위로 인식한다. px은 요소의 크기나 이미지의 크기 지정에 주로 사용된다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
text-align: center;
}
div {
font-size: 14px;
font-weight: bold;
padding: 2em; /* 14px * 2 = 28px */
background-color: rgba(255, 0, 0, 0.2);
}
</style>
</head>
<body>
<div>Font size: 14px</div>
</body>
</html>
%
는 백분률 단위의 상대 단위이다. 요소에 지정된 사이즈(상속된 사이즈나 디폴트 사이즈)에 상대적인 사이즈를 설정한다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-size: 14px;
text-align: center;
}
div {
font-size: 120%; /* 14px * 1.2 = 16.8px */
font-weight: bold;
padding: 2em; /* 16.8px * 2 = 33.6px */
background-color: rgba(255, 0, 0, 0.2);
}
</style>
</head>
<body>
<div>Font size: 14px * 120% → 16.8px</div>
</body>
</html>
em
은 배수(倍數) 단위로 상대 단위이다.
요소에 지정된 사이즈(상속된 사이즈나 디폴트 사이즈)에 상대적인 사이즈를 설정한다. 예를 들어 1em
은 요소에 지정된 사이즈와 같고 2em
은 요소에 지정된 사이즈의 2배이다. 폰트 사이즈 설정이나 콘텐츠를 포함하는 컨테이너의 크기 설정에 사용하면 상대적인 설정이 가능하여 편리하다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-size: 14px;
text-align: center;
}
div {
font-size: 1.2em; /* 14px * 1.2 = 16.8px */
font-weight: bold;
padding: 2em; /* 16.8px * 2 = 33.6px */
background-color: rgba(255, 0, 0, 0.2);
}
</style>
</head>
<body>
<div>Font size: 1.2em → 14px * 1.2 = 16.8px</div>
</body>
</html>
중첩된 자식 요소에
em
을 지정하면 모든 자식 요소의 사이즈에 영향을 미치기 때문에 주의하여야 한다. 상대 단위인 em의 기준이상속
의 영향으로 바뀔 수 있기 때문이다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-size: 14px;
text-align: center;
}
div {
font-size: 1.2em; /* 14px * 1.2 = 16.8px */
font-weight: bold;
padding: 2em;
}
.box1 { background-color: rgba(255, 0, 0, 0.2); }
.box2 { background-color: rgba(255, 0, 0, 0.6); }
.box3 { background-color: rgba(255, 0, 0, 0.8); }
</style>
</head>
<body>
<div class='box1'>
Font size: 1.2em ⇒ 14px * 1.2 = 16.8px
<div class='box2'>
Font size: 1.2em ⇒ 16.8px * 1.2 = 20.16px
<div class='box3'>
Font size: 1.2em ⇒ 20.16px * 1.2 = 24.192px
</div>
</div>
</div>
</body>
</html>
em
의 기준은 상속의 영향으로 바뀔 수 있다. 즉, 상황에 따라 1.2em
은 각기 다른 값을 가질 수 있다.
rem
은 최상위 요소(html)의 사이즈를 기준으로 삼는다.rem
의 r은root
를 의미한다.
<!DOCTYPE html>
<html>
<head>
<style>
html {
font-size: 14px;
/* font-size 미지정 시에는 16px */
}
div {
font-size: 1.2rem; /* html font-size: 14px * 1.2 = 16.8px */
font-weight: bold;
padding: 2em;
text-align: center;
}
.box1 { background-color: rgba(255, 0, 0, 0.2); }
.box2 { background-color: rgba(255, 0, 0, 0.6); }
.box3 { background-color: rgba(255, 0, 0, 0.8); }
</style>
</head>
<body>
<div class='box1'>
Font size: 1.2rem ⇒ 14px * 1.2 = 16.8px
<div class='box2'>
Font size: 1.2rem ⇒ 14px * 1.2 = 16.8px
<div class='box3'>
Font size: 1.2rem ⇒ 14px * 1.2 = 16.8px
</div>
</div>
</div>
</body>
</html>
사용자가 브라우저의 기본 폰트 크기를 변경하더라도 이에 따라 웹사이트의 레이아웃을 적절히 조정할 수 있다는 장점이 있다. 따라서 폰트 사이즈 뿐만이 아니라 콘텐츠의 크기에 따라 가변적으로 대응하여야 하는
wrapper 요소(container)
등에 적합하다.
.container {
width: 70rem; /* 70rem ⇒ 14px * 70 = 980px */
}
반응형 웹디자인은 화면의 크기에 동적으로 대응하기 위해 %
단위를 자주 사용한다. 하지만 %
단위는 em
과 같이 상속에 의해 부모 요소에 상대적 영향을 받는다.
Viewport단위
는 상대적인 단위로viewport
를 기준으로 한 상대적 사이즈를 의미한다.
단위 | Description |
---|---|
vw | viewport 너비의 1/100 |
vh | viewport 높이의 1/100 |
vmin | viewport 너비 또는 높이 중 작은 쪽의 1/100 |
vmax | viewport 너비 또는 높이 중 큰 쪽의 1/100 |
예를 들어 viewport 너비가 1000px, 높이가 600px인 경우,
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0px; }
.item {
width: 50vw;
height: 100vh;
text-align: center;
line-height: 100vh;
font-size: 4rem;
color: white;
}
.item1 { background-color: red; }
.item2 { background-color: orange; }
</style>
</head>
<body>
<div class='item item1'>item1</div>
<div class='item item2'>item2</div>
</body>
</html>
색상을 지정하기 위해
키워드(red, blue…)
를 사용할 수 있다. 사용이 간편하다는 장점이 있으나 표현할 수 있는 색상의 수는 제한된다.
<!DOCTYPE html>
<html>
<body>
<h2 style="background-color:red">
Red background-color
</h2>
<h2 style="background-color:green">
Green background-color
</h2>
<h2 style="background-color:blue;color:white">
Blue background-color and white text color
</h2>
<h2 style="background-color:orange">
Orange background-color
</h2>
<h2 style="background-color:yellow">
Yellow background-color
</h2>
<h2 style="background-color:cyan">
Cyan background-color
</h2>
<h2 style="background-color:black;color:white">
Black background-color and white text color
</h2>
</body>
</html>
더욱 다양한 색상을 표현하기 위해 아래와 같은 색상 표현 단위를 사용할 수 있다.
단위 | 사용예 |
---|---|
HEX 코드 단위 (Hexadecimal Colors) | #000000 |
RGB (Red, Green, Blue) | rgb(255, 255, 0) |
RGBA (Red, Green, Blue, Alpha/투명도) | rgba(255, 255, 0, 1) |
HSL (Hue/색상, Saturation/채도, Lightness/명도) | hsl(0, 100%, 25%) |
HSLA (Hue, Saturation, Lightness, Alpha) | hsla(60, 100%, 50%, 1) |
모든 HTML 요소는 Box 형태의 영역을 가지고 있다.
Box는 콘텐트(Content), 패딩(Padding), 테두리(Border), 마진(Margin)로 구성된다.
브라우저는 박스 모델의 크기
프로퍼티(색, 배경, 모양 등)
위치
를 근거로 하여 렌더링을 실행한다. 웹디자인은 콘텐츠를 담을 박스 모델을 정의
하고 CSS 프로퍼티를 통해 스타일(배경, 폰트와 텍스트 등)
과 위치 및 정렬을 지정
하는 것이라고 할 수 있다.
명칭 | 설명 |
---|---|
Content | 요소의 텍스트나 이미지 등의 실제 내용이 위치하는 영역이다. width, height 프로퍼티를 갖는다. |
Padding | 테두리(Border) 안쪽에 위치하는 요소의 내부 여백 영역이다. padding 프로퍼티 값은 패딩 영역의 두께를 의미하며 기본색은 투명(transparent)이다. 요소에 적용된 배경의 컬러, 이미지는 패딩 영역까지 적용된다. |
Border | 테두리 영역으로 border 프로퍼티 값은 테두리의 두께를 의미한다. |
Margin | 테두리(Border) 바깥에 위치하는 요소의 외부 여백 영역이다. margin 프로퍼티 값은 마진 영역의 두께를 의미한다. 기본적으로 투명(transparent)하며 배경색을 지정할 수 없다. |
<!DOCTYPE html>
<html>
<head>
<style>
div {
/* 배경색의 지정: 콘텐츠 영역과 패딩 영역에 적용된다. */
background-color: lightgrey;
/* 콘텐츠 영역의 너비 */
width: 300px;
/* 패딩 영역의 두께 */
padding: 25px;
/* 테두리: 두께 형태 색상 */
border: 25px solid navy;
/* 마진 영역의 두께 */
margin: 25px;
}
</style>
</head>
<body>
<h2>Box Model</h2>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</body>
</html>
width와 height 프로퍼티는 요소의 너비와 높이를 지정하기 위해 사용된다.
이때 지정되는 요소의 너비와 높이는 콘텐츠 영역
을 대상으로 한다. box-sizing
프로퍼티에 기본값인 content-box
가 적용되었기 때문이다. box-sizing
프로퍼티에 border-box
를 적용하면 콘텐츠 영역, padding, border가 포함된 영역을 width / height 프로퍼티의 대상으로 지정할 수 있다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
div {
width: 300px;
height: 100px;
background-color: cornsilk;
border: 5px solid navy;
}
</style>
</head>
<body>
<div>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</body>
</html>
기본적으로 width와 height 프로퍼티는 콘텐츠 영역
을 대상으로 요소의 너비와 높이를 지정하므로 박스 전체 크기
는 아래와 같이 계산한다.
전체 너비
width + left padding + right padding + left border + right border + left margin + right margin
전체 높이
height + top padding + bottom padding + top border + bottom border + top margin + bottom margin
Width
492px = 20px + 6px + 20px + 400px + 20px + 6px + 20px
Height
192px = 20px + 6px + 20px + 100px + 20px + 6px + 20px
width와 height 프로퍼티의 초기값은 auto
로써 이것은 브라우저가 상황에 따라 적당한 width와 height 값을 계산할 것을 의미한다.
예를 들어 block 요소의 경우, width는 부모 요소의 100%, height는 콘텐츠의 높이(+ 약간의 여분)가 지정된다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
div {
background-color: beige;
}
</style>
</head>
<body>
<div>This is a div</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
div {
background-color: beige;
height: 100px;
width: 50%;
}
</style>
</head>
<body>
<div>This is a div</div>
</body>
</html>
width와 height 프로퍼티를 비롯한 모든 박스모델 관련 프로퍼티(margin, padding, border, box-sizing 등)는 상속되지 않는다.
margin / padding 프로퍼티는 content의 4개 방향(top, right, left, bottom)에 대하여 지정이 가능하다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
border: 5px solid red;
margin-top: 40px;
margin-right: 30px;
margin-bottom: 20px;
margin-left: 10px;
padding-top: 10px;
padding-right: 20px;
padding-bottom: 30px;
padding-left: 40px;
}
</style>
</head>
<body>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</body>
</html>
4개의 값을 지정할 때
margin: 25px 50px 75px 100px;
• margin-top: 25px;
• margin-right: 50px;
• margin-bottom: 75px;
• margin-left: 100px;
3개의 값을 지정할 때
margin: 25px 50px 75px;
• margin-top: 25px;
• margin-right: 50px; margin-left: 50px;
• margin-bottom: 75px
2개의 값을 지정할 때
margin: 25px 50px;
• margin-top: 25px; margin-bottom: 25px;
• margin-right: 50px; margin-left: 50px;
1개의 값을 지정할 때
margin: 25px;
• margin-top: 25px; margin-right: 25px; margin-bottom: 25px; margin-left: 25px;
<!DOCTYPE html>
<html>
<head>
<style>
div {
border: 5px solid red;
margin: 40px 30px 20px 10px;
padding: 10px 20px 30px 40px;
}
</style>
</head>
<body>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</body>
</html>
margin 프로퍼티에
auto
키워드를 설정하면 해당 요소를 브라우저 중앙에 위치 시킬 수 있다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
border: 5px solid red;
width: 600px;
margin: 0 auto;
}
</style>
</head>
<body>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</body>
</html>
요소 너비가 브라우저 너비보다 크면 가로 스크롤바가 만들어진다. 이 문제를 해결하기 위해서 max-width
프로퍼티를 사용할 수 있다. max-width
프로퍼티를 사용하면 브라우저 너비가 요소의 너비보다 좁아질 때 자동으로 요소의 너비가 줄어든다.
max-width
프로퍼티는 요소 너비의 최대값을,min-width
프로퍼티는 요소 너비의 최소값을 지정한다.
예를 들어max-width: 300px;
의 경우, 브라우저의 너비가 300px보다 작아지면 요소 너비는 브라우저의 너비에 따라서 작아진다.
min-width: 300px;
의 경우 브라우저의 너비가 300px보다 작아져도 요소 너비는 지정 너비(300px)을 유지한다.
border-style
프로퍼티는 테두리 선의 스타일을 지정한다.
<!DOCTYPE html>
<html>
<head>
<style>
p {
background: palegreen;
padding: 10px;
}
p.dotted { border-style: dotted; }
p.dashed { border-style: dashed; }
p.solid { border-style: solid; }
p.double { border-style: double; }
p.groove { border-style: groove; }
p.ridge { border-style: ridge; }
p.inset { border-style: inset; }
p.outset { border-style: outset; }
p.none { border-style: none; }
p.hidden { border-style: hidden; }
p.mix { border-style: dotted dashed solid double; }
</style>
</head>
<body>
<h2>border-style Property</h2>
<p class="dotted">dotted</p>
<p class="dashed">dashed</p>
<p class="solid">solid</p>
<p class="double">double</p>
<p class="groove">groove</p>
<p class="ridge">ridge</p>
<p class="inset">inset</p>
<p class="outset">outset</p>
<p class="none">none</p>
<p class="hidden">hidden</p>
<p class="mix">dotted dashed solid double</p>
</body>
</html>
프로퍼티 값의 갯수에 따라 4개 방향(top, right, left, bottom)에 대하여 지정이 가능하다.
<!DOCTYPE html>
<html>
<head>
<style>
p {
background: palegreen;
padding: 10px;
}
p.d1 {
/* four sides */
border-style: dashed;
}
p.d2 {
/* horizontal | vertical */
border-style: dotted solid;
}
p.d3 {
/* top | horizontal | bottom */
border-style: hidden double dashed;
}
p.d4 {
/* top | right | bottom | left */
border-style: none solid dotted dashed;
}
</style>
</head>
<body>
<p class="d1">border-style: dashed;</p>
<p class="d2">border-style: dotted solid;</p>
<p class="d3">border-style: hidden double dashed;</p>
<p class="d4">border-style: none solid dotted dashed;</p>
</body>
</html>
border-width
프로퍼티는 테두리의 두께를 지정한다. 프로퍼티 값의 갯수에 따라 4개 방향(top, right, left, bottom)에 대하여 지정이 가능하다.border-width
프로퍼티는border-style
과 함께 사용하지 않으면 적용되지 않는다.
<!DOCTYPE html>
<html>
<head>
<style>
p {
background: palegreen;
padding: 10px;
border-style: solid
}
p.one {
border-width: thin; /* 1px */
}
p.two {
border-width: medium; /* 3px */
}
p.three {
border-width: thick; /* 5px */
}
p.four {
border-width: 15px;
}
p.five {
border-width: 2px 10px 4px 20px;
}
</style>
</head>
<body>
<h2>border-width Property</h2>
<p>initial: 3px</p>
<p class="one">thin: 1px</p>
<p class="two">medium: 3px</p>
<p class="three">thick: 5px</p>
<p class="four">15px</p>
<p class="five">2px 10px 4px 20px</p>
</body>
</html>
border-color
프로퍼티는 테두리의 색상을 지정한다. 프로퍼티 값의 갯수에 따라 4개 방향(top, right, left, bottom)에 대하여 지정이 가능하다.border-color
프로퍼티는border-style
과 함께 사용하지 않으면 적용되지 않는다.
<!DOCTYPE html>
<html>
<head>
<style>
p {
background: palegreen;
padding: 10px;
border-style: solid;
}
p.one {
border-color: red;
}
p.two {
border-color: green;
}
p.three {
border-color: red green blue yellow;
}
</style>
</head>
<body>
<h2>border-color Property</h2>
<p class="one">border-color: red</p>
<p class="two">border-color: green</p>
<p class="three">border-color: red green blue yellow</p>
</body>
</html>
border-radius
프로퍼티는 테두리 모서리를 둥글게 표현하도록 지정한다.
프로퍼티 값은 길이를 나타내는 단위(px, em 등)
와 %
를 사용한다. 각각의 모서리에 border-radius 프로퍼티를 개별적으로 지정할 수도 있고 4개의 모서리를 short-hand로 한번에 지정할 수도 있다.
하나 혹은 두개의 반지름을 설정하여 각각의 모서리 굴곡을 설정할 수 있기 때문에 원 혹은 타원의 모양으로 정의가 가능하다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
background: #eaeaed;
color: #666;
display: inline-block;
width: 90px;
height: 90px;
line-height: 90px;
margin: 0 14px;
text-align: center;
}
.border-rounded {
/* 4 꼭지점에 대해 Radius 지정 */
border-radius: 5px;
}
.border-circle {
border-radius: 50%;
}
.border-football {
/* top-left & bottom-right | top-right & bottom-left */
border-radius: 15px 75px;
}
</style>
</head>
<body>
<div class="border-rounded">5px</div>
<div class="border-circle">50%</div>
<div class="border-football">15px 75px</div>
</body>
</html>
모든 모서리에 동일한 둥근 모서리 설정
.border-rounded {
border-radius: 20px;
/* 위 코드는 아래의 shorthand이다.
border-top-left-radius: 20px;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
border-bottom-left-radius: 20px;
*/
}
<!DOCTYPE html>
<html>
<head>
<style>
div {
background: #eaeaed;
color: #666;
width: 150px;
height: 150px;
line-height: 150px;
text-align: center;
}
.border-rounded {
/* 모든 모서리를 동일하게 설정 */
border-radius: 20px;
}
</style>
</head>
<body>
<div class="border-rounded">border-radius: 20px</div>
</body>
</html>
각각의 모서리를 개별적으로 설정
.border-rounded {
border-radius: 10px 40px 40px 10px;
/* 위 코드는 아래의 shorthand이다.
border-top-left-radius: 10px;
border-top-right-radius: 40px;
border-bottom-right-radius: 40px;
border-bottom-left-radius: 10px;
*/
}
<!DOCTYPE html>
<html>
<head>
<style>
div {
background: #eaeaed;
color: #666;
width: 200px;
height: 150px;
line-height: 150px;
text-align: center;
}
.border-rounded {
/* 각각의 모서리를 개별적으로 설정 */
border-radius: 10px 40px 40px 10px;
}
</style>
</head>
<body>
<div class="border-rounded">10px 40px 40px 10px</div>
</body>
</html>
두개의 반지름을 지정하여 타원형 둥근 모서리 설정
.border-rounded {
border-top-left-radius: 50px 25px;
}
<!DOCTYPE html>
<html>
<head>
<style>
div {
background: #eaeaed;
color: #666;
width: 300px;
height: 150px;
line-height: 150px;
text-align: center;
}
.border-rounded {
border-top-left-radius: 50px 25px;
}
</style>
</head>
<body>
<div class="border-rounded">border-top-left-radius: 50px 25px</div>
</body>
</html>
각각의 모서리에 타원형 둥근 모서리 축약 설정
.border-rounded {
border-radius: 50px 50px 0 0 / 25px 25px 0 0;
}
<!DOCTYPE html>
<html>
<head>
<style>
div {
background: #eaeaed;
color: #666;
width: 450px;
height: 150px;
padding: 10px;
}
.border-rounded {
border-radius: 10px 20px 30px 40px / 5px 10px 15px 20px;
}
</style>
</head>
<body>
<div class="border-rounded">
border-radius: 10px 20px 30px 40px / 5px 10px 15px 20px;
<ul>
<li>border-top-left-radius: 10px 5px;</li>
<li>border-top-right-radius: 20px 10px;</li>
<li>border-bottom-right-radius: 30px 15px;</li>
<li>border-bottom-left-radius: 40px 20px;</li>
</ul>
</div>
</body>
</html>
border
프로퍼티는border-width
,border-style
,border-color
를 한번에 설정하기 위한 shorthand 프로퍼티이다.
/* Syntax */
border: border-width border-style border-color;
p {
/* border-width border-style border-color */
border: 5px solid red;
}
width
, height
프로퍼티의 대상 영역을 변경할 수 있다.content-box
이다. 이는 width
, height
프로퍼티의 대상 영역이 content 영역
을 의미한다.border-box
로 지정하면 마진을 제외한 박스 모델 전체를width
, height
프로퍼티의 대상 영역으로 지정할 수 있어서 CSS Layout을 직관적으로 사용할 수 있게 한다.키워드 | 설명 |
---|---|
content-box | width, height 프로퍼티 값은 content 영역을 의미한다. (기본값) |
border-box | width, height 프로퍼티 값은 content 영역, padding, border가 포함된 값을 의미한다. |
<!DOCTYPE html>
<html>
<head>
<style>
.content-box {
width: 600px;
border: 10px solid;
padding: 50px;
margin: 50px;
background-color: red;
}
.border-box {
box-sizing: border-box;
width: 600px;
border: 10px solid;
padding: 50px;
margin: 50px;
background-color: red;
}
</style>
</head>
<body>
<div class="content-box">content-box</div>
<div class="border-box">border-box</div>
</body>
</html>
box-sizing
프로퍼티는 상속되지 않는다.
사용하도록 초기화하려면 아래와 같이 정의한다.html { box-sizing: border-box; } *, *:before, *:after { box-sizing: inherit;
display 프로퍼티는 layout 정의에 자주 사용되는 중요한 프로퍼티이다.
프로퍼티값 키워드 | 설명 |
---|---|
block | block 특성을 가지는 요소(block 레벨 요소)로 지정 |
inline | inline 특성을 가지는 요소(inline 레벨 요소)로 지정 |
inline-block | inline-block 특성을 가지는 요소(inline-block 레벨 요소)로 지정 |
none | 해당 요소를 화면에 표시하지 않는다 (공간조차 사라진다) |
모든 HTML 요소는 아무런 CSS를 적용하지 않아도 기본적으로 브라우저에 표현되는 디폴트 표시값을 가진다. HTML 요소는 block
또는 inline
특성을 갖는다.
display 프로퍼티는 상속되지 않는다.
block 레벨 요소
는 아래와 같은 특징을 갖는다.
width
height
margin
padding
프로퍼티 지정이 가능하다.<!DOCTYPE html>
<html>
<head>
<style>
div:nth-of-type(1) {
background-color: #FFA07A;
padding: 20px;
}
div:nth-of-type(2) {
background-color: #FF7F50;
padding: 20px;
width: 300px;
}
</style>
</head>
<body>
<div>
<h2>블록 레벨 요소</h2>
<p>width, height 미지정 → width: 100%; height: auto;</p>
</div>
<div>
<h2>블록 레벨 요소</h2>
<p>width: 300px → width: 300px; height: auto;</p>
</div>
</body>
</html>
inline레벨 요소
는 아래와 같은 특징을 갖는다.
content
의 너비만큼 가로폭을 차지한다.width
height
margin-top
margin-bottom
프로퍼티를 지정할 수 없다. 상, 하 여백은 line-height
로 지정한다.<!DOCTYPE html>
<html>
<head>
<style>
span {
background-color: red;
color: white;
padding: 10px;
/* width, height, margin-top, margin-bottom 프로퍼티를 지정할 수 없다. */
/* width: 200px; */
/* margin: 10px; */
/* 상, 하 여백은 line-height로 지정한다. */
/* line-height: 50px; */
}
</style>
</head>
<body>
<h1>My <span>Important</span> Heading</h1>
<span>Inline</span>
<span>Inline</span><span>Inline</span>
</body>
</html>
block
과 inline
레벨 요소의 특징을 모두 갖는다. inline 레벨 요소와 같이 한 줄에 표현되면서 width
height
margin
프로퍼티를 모두 지정할 수 있다.
width
height
margin
padding
프로퍼티를 모두 정의할 수 있다. 상, 하 여백을 margin
과 line-height
두가지 프로퍼티 모두를 통해 제어할 수 있다.content
의 너비만큼 가로폭을 차지한다.<!DOCTYPE html>
<html>
<head>
<style>
.wrapper {
font-size: 0; /*요소간 간격을 제거*/
}
.inline-block {
display: inline-block;
vertical-align: middle; /* inline-block 요소 수직 정렬 */
border: 3px solid #73AD21;
font-size: 16px;
}
.box1 {
width: 300px;
height: 70px;
}
.box2 {
width: 300px;
height: 150px;
}
</style>
</head>
<body>
<div class="inline-block box1">inline-block height 70px</div>
<div class="inline-block box2">inline-block height 150px</div>
<div class="wrapper">
<div class="inline-block box1">inline-block height 70px</div>
<div class="inline-block box2">inline-block height 150px</div>
</div>
</body>
</html>
visibility
프로퍼티는 요소를 보이게 할 것인지 보이지 않게 할 것인지를 정의한다. 즉, 요소의 렌더링 여부를 결정한다.
프로퍼티값 키워드 | 설명 |
---|---|
visible | 해당 요소를 보이게 한다 (기본값) |
hidden | 해당 요소를 보이지 않게 한다. |
display: none; 은 해당 요소의 공간까지 사라지게 하지만 visibility: hidden; 은 해당 요소의 공간은 사라지지 않고 남아있게 된다. | |
collapse | table 요소에 사용하며 행이나 열을 보이지 않게 한다. |
none | table 요소의 row나 column을 보이지 않게 한다. IE, 파이어폭스에서만 동작하며 크롬에서는 hidden과 동일하게 동작한다. |
<!DOCTYPE html>
<html>
<head>
<style>
.visible { visibility: visible; }
.hidden { visibility: hidden; }
table, td { border: 1px solid black; }
.collapse { visibility: collapse; }
/* .collapse { visibility: hidden; } */
</style>
</head>
<body>
<h1 class="visible">visibility: visible</h1>
<h1 class="hidden">visibility: hidden</h1>
<h1 style="display:none">display:none</h1>
<table>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr class="collapse">
<td>C</td>
<td>D</td>
</tr>
</table>
</body>
</html>
opacity
프로퍼티는 요소의 투명도를 정의한다. 0.0
~ 1.0
의 값을 입력하며 0.0은 투명
1.0은 불투명
을 의미한다.
<!DOCTYPE html>
<html>
<head>
<style>
div, img {
float: left;
width: 150px;
height: 150px;
margin: 30px;
background-color: blue;
color: white;
opacity: 0.5;
transition: opacity 1s;
}
div:hover, img:hover {
opacity: 1.0;
}
</style>
</head>
<body>
<div>opacity: 0.5</div>
<img src="https://poiemaweb.com/img/doug.jpg" alt="doug">
</body>
</html>
요소에 배경 이미지를 지정한다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-image: url("http://poiemaweb.com/img/bg/dot.png");
}
</style>
</head>
<body>
<h3>Background Image</h3>
</body>
</html>
배경 이미지의 반복을 지정한다. 수직, 수평 또는 수직과 수평 모두의 반복을 지정할 수 있다.
설정된 이미지의 크기가 화면보다 작으면 자동으로 이미지가 반복 출력되어 화면을 채우게 된다. 이것은 background-repeat
프로퍼티의 기본값이 repeat
이기 때문이다. x축으로만 배경 이미지를 반복할 경우, background-repeat
프로퍼티값에 repeat-x
, y축으로만 배경 이미지를 반복할 경우, repeat-y
를 설정한다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-image: url("http://poiemaweb.com/img/bg/dot.png");
background-repeat: repeat-x;
}
</style>
</head>
<body>
<h3>background-repeat: repeat-x;</h3>
</body>
</html>
반복 출력을 멈추고 싶은 경우, background-repeat
프로퍼티값에 no-repeat
를 설정한다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-image: url("http://poiemaweb.com/img/bg/dot.png");
background-repeat: no-repeat;
}
</style>
</head>
<body>
<h3>background-repeat: no-repeat;</h3>
</body>
</html>
background-image에 복수개의 이미지를 설정할 경우,먼저 설정된 이미지
가 전면에 출력된다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-image: url("http://poiemaweb.com/img/bg/dot.png"), url("http://poiemaweb.com/img/bg/paper.gif");
background-repeat: no-repeat, repeat;
}
</style>
</head>
<body>
<h3>background-repeat: no-repeat, repeat;</h3>
</body>
</html>
배경 이미지의 사이즈를 지정한다. 배경 이미지의 고유 비율을 유지하기 때문에 설정에 따라 이미지의 일부가 보이지 않을 수 있다.
프로퍼티값은 px
%
cover
contain
등을 사용한다. 배경이미지의 width
height
를 모두 설정할 수 있다. 이때 첫번째 값은 width
두번째 값은 height
를 의미한다.
px값 지정
배경이미지 크기가 지정된 px값 그대로 설정된다. 첫번째 값은 width, 두번째 값은 height를 의미한다..bg { background-size: 700px 500px; }
%값 지정
배경이미지 크기가 지정된 %값에 비례하여 설정된다. 첫번째 값은 width, 두번째 값은 height를 의미한다.
화면을 줄이거나 늘리면 배경이미지의 크기도 따라서 변경되어 찌그러지는 현상이 나타난다..bg { background-size: 100% 100%; }
cover 지정
배경이미지의 크기 비율을 유지한 상태에서 부모 요소의width
height
중큰 값
에 배경이미지를 맞춘다. 따라서 이미지의 일부가 보이지 않을 수 있다..bg { background-size: cover; }
contain 지정
배경이미지의 크기 비율을 유지한 상태에서 부모 요소의 영역에 배경이미지가 보이지 않는 부분없이 전체가 들어갈 수 있도록 이미지 스케일을 조정한다..bg { background-size: contain; }
width, height의 프로퍼티값은 공백으로 구분하여야 한다. 프로퍼티값을 쉼표로 구분하면 다른 배경이미지의 너비를 지정하는 것으로 인식되기 때문에 주의가 필요하다.
body {
background-image: url("front.png"), url("back.png");
background-repeat: no-repeat, no-repeat;
background-size: 100%, 500px;
}
일반적으로 화면을 스크롤하면 배경 이미지도 함께 스크롤된다. 화면이 스크롤되더라도 배경이미지는 스크롤되지 않고 고정되어 있게 하려면 background-attachment
프로퍼티에 fixed
키워드를 지정한다.
<!DOCTYPE html>
<html>
<head>
<style>
*, *:after, *:before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width:100%;
height:100%;
}
.bg-wrap {
/* page-wrap 보다 bg-wrap이 작은 경우, page-wrap이 가리는 문제를 해결 */
min-height: 600px;
height: 100%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
/* 마진 상쇄 문제 해결을 위한 코드
https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
*/
overflow: auto;
/* or padding: 0.1px; */
}
.parallax {
background-image: url("http://poiemaweb.com/img/bg/stock-photo-125979219.jpg");
/* parallax scrolling effect */
background-attachment: fixed;
}
.normal {
background-image: url("http://poiemaweb.com/img/bg/stock-photo-155153867.jpg");
}
#page-wrap {
width: 400px;
/* 마진 상쇄 발생 */
margin: 50px auto;
padding: 30px;
background: white;
box-shadow: 0 0 20px black;
/* size/line-height | family */
font: 15px/2 Georgia, Serif;
}
</style>
</head>
<body>
<div class="bg-wrap parallax">
<div id="page-wrap">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid ipsum maxime libero, impedit necessitatibus quas blanditiis tenetur vero aut esse unde ab similique, delectus placeat enim quae expedita excepturi laboriosam.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid ipsum maxime libero, impedit necessitatibus quas blanditiis tenetur vero aut esse unde ab similique, delectus placeat enim quae expedita excepturi laboriosam.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid ipsum maxime libero, impedit necessitatibus quas blanditiis tenetur vero aut esse unde ab similique, delectus placeat enim quae expedita excepturi laboriosam.</p>
</div>
</div>
<div class="bg-wrap normal"></div>
</body>
</html>
일반적으로 background-image
는 좌상단부터 이미지를 출력한다. 이때 background-position
프로퍼티를 사용하면 이미지의 좌표(xpos, ypos)를 지정 할 수 있다. 기본값은 background-position: 0% 0%;
로 배경이미지는 우측 상단에 위치하게 된다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
}
div {
background-image: url("http://poiemaweb.com/img/bg/dot.png");
background-color: #FFEE99;
background-repeat: no-repeat;
width: 32vw;
height: 200px;
margin-bottom: 2vw;
float: left;
}
div:not(:nth-of-type(3n+1)) {
margin-left: 2vw;
}
.example1 {
background-position: top;
}
.example2 {
background-position: bottom;
}
.example3 {
background-position: center;
}
.example4 {
background-position: left;
}
.example5 {
background-position: right;
}
.example6 {
/* <percentage> values */
background-position: 25% 75%;
}
.example7 {
/*
<length> values
xpos ypos
*/
background-position: 10px 20px;
}
.example8 {
background-image: url("http://poiemaweb.com/img/bg/dot.png"), url("http://poiemaweb.com/img/bg/dot.png");
background-position: 0px 0px, center;
}
</style>
</head>
<body>
<div>default(0% 0%)</div>
<div class="example1">top</div>
<div class="example2">bottom</div>
<div class="example3">center</div>
<div class="example4">left</div>
<div class="example5">right</div>
<div class="example6">25% 75%</div>
<div class="example7">10px 20px</div>
<div class="example8">0px 0px, center</div>
</body>
</html>
background-color
프로퍼티는 요소의 배경 색상을 지정한다. 색상값 또는transparent
키워드를 지정할 수 있다.
.bg-col-white {
background-color: rgb(255, 255, 255);
}
.bg-col-red {
background-color: red;
}
background-color, background-image, background-repeat, background-position를 한번에 정의하기 위한 Shorthand Syntax이다.
// order
background: color || image || repeat || attachment || position
<!DOCTYPE html>
<html>
<head>
<style>
div {
/* background: color || image || repeat || attachment || position */
background: #FFEE99 url("http://poiemaweb.com/img/bg/dot.png") no-repeat center;
width: 50vw;
height: 300px;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
텍스트의 크기를 정의한다.
<!DOCTYPE html>
<html>
<head>
<style>
.font-size-40 { font-size: 40px; }
.font-size-2x { font-size: 2.0em; }
.font-size-150ps { font-size: 150%; }
.font-size-large { font-size: large; }
</style>
</head>
<body>
<p>default font size: 16px</p>
<p class='font-size-40'>font-size: 40px</p>
<p class='font-size-2x'>font-size: 2.0em</p>
<p class='font-size-150ps'>font-size: 150%</p>
<p class='font-size-large'>font-size: large</p>
</body>
</html>
폰트를 지정한다. 컴퓨터에 해당 폰트가 설치되어 있지 않으면 적용되지 않는다.
폰트는 여러 개를 동시에 지정이 가능하다. 첫번째 지정한 폰트가 클라이언트 컴퓨터에 설치되어 있지 않은 경우, 다음에 지정된 폰트를 적용한다.
마지막에 지정하는 폰트는 대부분의 OS에 기본적으로 설치되어 있는 generic-family 폰트(Serif, Sans-serif, Mono space)를 지정하는 것이 일반적이다.
폰트명은 따옴표로 감싸주며 폰트명이 한단어인 경우는 따옴표로 감싸주지 않아도 된다.
<!DOCTYPE html>
<html>
<head>
<style>
.serif {
font-family: "Times New Roman", Times, serif;
}
.sans-serif {
font-family: Arial, Helvetica, sans-serif;
}
.monospace {
font-family: "Courier New", Courier, monospace;
}
</style>
</head>
<body>
<h1>font-family</h1>
<p class="serif">Times New Roman font.</p>
<p class="sans-serif">Arial font.</p>
<p class="monospace">Courier New font.</p>
</body>
</html>
font-style
프로퍼티는 이탤릭체의 지정,font-weight
프로퍼티는 폰트 굵기 지정에 사용된다.
<!DOCTYPE html>
<html>
<head>
<style>
p { font-size: 2.0em; }
/*
font-style
normal / italic / oblique
*/
.italic {
font-style: italic;
}
/*
font-weight
100 ~ 900 or normal / bold / lighter / bolder
*/
.light {
font-weight: lighter;
}
.thick {
font-weight: bold;
}
.thicker {
font-weight: 900;
}
</style>
</head>
<body>
<p>normal style.</p>
<p class="italic">font-style: italic</p>
<p class="light">font-weight: lighter</p>
<p class="thick">font-weight: bold</p>
<p class="thicker">font-weight: 900</p>
</body>
</html>
font-style
font-variant
font-weight
font-size
line-height
font-family
를 한 번에 작성 할 수 있는 Shorthand Syntax 이다.
font : font-style(optional) font-variant(optional) font-weight(optional) font-size(mandatory) line-height(optional) font-family(mandatory)
/* size | family */
font: 2em "Open Sans", serif;
/* style | size | family */
font: italic 2em "Open Sans", sans-serif;
/* style | variant | weight | size/line-height | family */
font: italic small-caps bolder 16px/1.2 monospace;
/* style | variant | weight | size/line-height | family */
/* font-variant: small-caps; 소문자를 대문자로 만든다. 단 크기는 일반 대문자에 비해 더 작다.*/
font: italic small-caps bolder 16px/3 cursive;
텍스트의 높이를 지정한다. 텍스트 수직 정렬에도 응용되어 사용된다.
<!DOCTYPE html>
<html>
<head>
<style>
.small {
line-height: 70%; /* 16px * 70% */
}
.big {
line-height: 1.2; /* 16px * 1.2 */
}
.lh-3x {
line-height: 3.0; /* 16px * 3 */
}
</style>
</head>
<body>
<p>
default line-height.<br>
default line-height.<br>
대부분 브라우저의 default line height는 약 110% ~ 120%.<br>
</p>
<p class="small">
line-height: 70%<br>
line-height: 70%<br>
</p>
<p class="big">
line-height: 1.2<br>
line-height: 1.2<br>
</p>
<p class="lh-3x">
line-height: 3.0<br>
line-height: 3.0<br>
</p>
</body>
</html>
a 요소의
line-height
값과 a 요소를 감싸는 div 요소의height
값을 일치시켜 하나의 요소로 동작하게 할 수 있다.
<!DOCTYPE html>
<html>
<head>
<style>
.button {
width: 150px;
height: 70px;
background-color: #FF6A00;
border-radius: 30px;
box-shadow: 5px 5px 5px #A9A9A9;
}
.button > a {
display: block;
font: italic bold 2em/70px Arial, Helvetica, sans-serif;
text-decoration: none;
text-align: center;
}
</style>
</head>
<body>
<div class="button">
<a href="#">Click</a>
</div>
</body>
</html>
글자 사이의 간격을 지정한다.
<!DOCTYPE html>
<html>
<head>
<style>
.loose {
letter-spacing: 2px;
}
.tight {
letter-spacing: -1px;
}
</style>
</head>
<body>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
<p class="loose">Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
<p class="tight">Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
</body>
</html>
텍스트의 수평 정렬을 정의한다.
<!DOCTYPE html>
<html>
<head>
<style>
h1 { text-align: center; }
h3 { text-align: right; }
p.left { text-align: left; }
p.justify { text-align: justify; }
a { text-align: center; }
</style>
</head>
<body>
<h1>Lorem ipsum</h1>
<h3>2016.03.07</h3>
<p class="left">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p class="justify">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<a href='#'>Reference</a>
</body>
</html>
a 요소에 대한 중앙 정렬은 적용되지 않았다. 이는 a 요소는 inline 요소
이기 때문이다. inline
요소는 width
프로퍼티가 없으므로 중앙 개념이 존재하지 않는다. a 요소에 display: block;
을 지정한다면 중앙 정렬이 가능하다.
text-decoration
프로퍼티를 사용하여 링크 underline을 제거할 수 있다. 또는 텍스트에underline
overline
line-through
를 추가할 수도 있다.
<!DOCTYPE html>
<html>
<head>
<style>
a { text-decoration: none; }
p:nth-of-type(1) { text-decoration: overline; }
p:nth-of-type(2) { text-decoration: line-through; }
p:nth-of-type(3) { text-decoration: underline; }
</style>
</head>
<body>
<a href='#'>text-decoration: none</a>
<p>text-decoration: overline</p>
<p>text-decoration: line-through</p>
<p>text-decoration: underline</p>
</body>
</html>
white space는 공백(space), 들여쓰기(tab), 줄바꿈(line break)을 의미한다.
html은 기본적으로 연속된 공백(space)
들여쓰기(tab)
는 1번만 실행되며 줄바꿈(line break)
은 무시된다. 또한 텍스트는 부모의 가로 영역을 벗어나지 않고 자동 줄바꿈(wrap)
된다. white-space
프로퍼티는 이러한 기본 동작을 제어하기 위한 프로퍼티이다.
프로퍼티값 | line break | space/tab | wrapping(자동줄바꿈) |
---|---|---|---|
normal | 무시 | 1번만 반영 | O |
nowrap | 무시 | 1번만 반영 | X |
pre | 반영 | 그대로 반영 | X |
pre-wrap | 반영 | 그대로 반영 | O |
pre-line | 반영 | 1번만 반영 | O |
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 150px;
height: 150px;
padding: 10px;
margin: 40px;
border-radius: 6px;
border-color: gray;
border-style: dotted;
/*overflow: hidden;*/
}
.normal { white-space: normal; }
.nowrap { white-space: nowrap; }
.pre { white-space: pre; }
.pre-wrap { white-space: pre-wrap; }
.pre-line { white-space: pre-line; }
</style>
</head>
<body>
<h1>white-space</h1>
<div class="normal"><h3>normal</h3>Lorem ipsum
dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
<div class="nowrap"><h3>nowrap</h3>Lorem ipsum
dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
<div class="pre"><h3>pre</h3>Lorem ipsum
dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
<div class="pre-wrap"><h3>pre-wrap</h3>Lorem ipsum
dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
<div class="pre-line"><h3>pre-line</h3>Lorem ipsum
dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
</body>
</html>
float
대신inline-block
을 사용하여 가로정렬도 가능하다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Infinite looping Crousel Slider</title>
<style>
@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,400);
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #58666e;
background-color: #f0f3f4;
}
.carousel-view {
/* 자식 컨텐츠 너비에 fit */
display: inline-block;
position: relative;
margin: 0 auto;
border: 1px dotted red;
}
.carousel-container {
/* 자식 컨텐츠의 줄바꿈을 무시하여 1줄로 가로 정렬한다. */
white-space: nowrap;
/* inline-block 레벨 요소 뒤에 공백(엔터, 스페이스 등)이 있는 경우,
정의하지 않은 space(4px)가 자동 지정된다. 이것을 회피하는 방법이다. */
font-size: 0;
margin: 0;
padding: 0;
}
.carousel-item {
display: inline-block;
list-style: none;
padding: 5px;
}
.carousel-item:last-child {
margin-right: 0;
}
.carousel-control {
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 2em;
color: #fff;
background-color: transparent;
border-color: transparent;
cursor: pointer;
z-index: 99;
}
.carousel-control:focus {
outline: none;
}
.carousel-control.prev {
left: 0;
}
.carousel-control.next {
right: 0;
}
</style>
</head>
<body>
<div id="carousel" class="carousel-view">
<button class="carousel-control prev">«</button>
<ul class="carousel-container">
<li class="carousel-item">
<a href="#">
<img src="http://via.placeholder.com/400x150/3498db/fff&text=1">
</a>
</li>
<li class="carousel-item">
<a href="#">
<img src="http://via.placeholder.com/400x150/3498db/fff&text=2">
</a>
</li>
<li class="carousel-item">
<a href="#">
<img src="http://via.placeholder.com/400x150/3498db/fff&text=3">
</a>
</li>
</ul>
<button class="carousel-control next">»</button>
</div>
</body>
</html>
부모 영역을 벗어난 wrapping(자동줄바꿈)이 되지 않은 텍스트의 처리 방법을 정의한다. 이 프로퍼티를 사용하기 위해서는 조건이 필요하다.
width
프로퍼티가 지정되어 있어야 한다. 이를 위해 필요할 경우 block 레벨 요소
로 변경하여야 한다.white-space
프로퍼티를 nowrap
으로 설정한다.overflow
프로퍼티에 반드시 visible
이외의 값이 지정되어 있어야 한다./* 부모 영역을 벗어난 텍스트를 잘라내어 보이지 않게 하고 말줄임표(...)를 표시한다. */
.truncate {
width: 150px; /* width가 지정되어 있어야 한다. */
white-space: nowrap; /* 자동 줄바꿈을 방지 */
overflow: hidden; /* 반드시 "visible" 이외의 값이 지정되어 있어야 한다. */
text-overflow: ellipsis; /* ellipsis or clip */
}
text-overflow 프로퍼티에 설정할 수 있는 프로퍼티 값은 아래와 같다.
프로퍼티값 | Description |
---|---|
clip | 영역을 벗어난 텍스트를 표시하지 않는다. (기본값) |
ellipsis | 영역을 벗어난 텍스트를 잘라내어 보이지 않게 하고 말줄임표(…)를 표시한다. |
string | 프로퍼티 값으로 지정한 임의의 문자열을 출력한다. |
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
div {
width: 150px; /* width가 지정되어 있어야 한다. */
height: 150px;
padding: 10px;
margin: 40px;
border-radius: 6px;
border-color: gray;
border-style: dotted;
white-space: nowrap; /* 자동 줄바꿈을 방지 */
overflow: hidden; /* 반드시 "visible" 이외의 값이 지정되어 있어야 한다. */
}
.clip { text-overflow: clip; }
.ellipsis { text-overflow: ellipsis; }
</style>
</head>
<body>
<h1>text-overflow</h1>
<div class="clip">
<h3>clip</h3>
Lorem ipsum dolor sit amet, consectetur adipisicing elit
</div>
<div class="ellipsis">
<h3>ellipsis</h3>
Lorem ipsum dolor sit amet, consectetur adipisicing elit
</div>
</body>
</html>
한 단어의 길이가 길어서 부모 영역을 벗어난 텍스트의 처리 방법을 정의한다.
link 등을 표기할 때 그 길이가 매우 길어지는데 이 프로퍼티를 사용하지 않으면 부모 영역을 넘어가게 된다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
div {
width: 150px;
height: 150px;
padding: 10px;
margin: 40px;
border-radius: 6px;
border-color: gray;
border-style: dotted;
}
.word-wrap { word-wrap: break-word; }
</style>
</head>
<body>
<h1>word-wrap</h1>
<div>
Floccinaucinihilipilification https://poiemaweb.com/css3-font-text
</div>
<div class="word-wrap">
Floccinaucinihilipilification https://poiemaweb.com/css3-font-text
</div>
</body>
</html>
한 단어의 길이가 길어서 부모 영역을 벗어난 텍스트의 처리 방법을 정의한다.
word-wrap
프로퍼티는 단어를 어느 정도는 고려하여 개행하지만(.,- 등을 고려한다) word-break: break-all;
는 단어를 고려하지 않고 부모 영역에 맞추어 강제 개행한다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
div {
width: 150px;
height: 150px;
padding: 10px;
margin: 40px;
border-radius: 6px;
border-color: gray;
border-style: dotted;
}
.word-wrap { word-wrap: break-word; }
.word-break { word-break: break-all; }
</style>
</head>
<body>
<div>
Floccinaucinihilipilification https://poiemaweb.com/css3-font-text
</div>
<h1>word-wrap</h1>
<div class="word-wrap">
Floccinaucinihilipilification https://poiemaweb.com/css3-font-text
</div>
<h1>word-break</h1>
<div class="word-break">
Floccinaucinihilipilification https://poiemaweb.com/css3-font-text
</div>
</body>
</html>
position
프로퍼티는 요소의 위치를 정의한다.top
bottom
left
right
프로퍼티와 함께 사용하여 위치를 지정한다.
static
은 position 프로퍼티의 기본값으로 position 프로퍼티를 지정하지 않았을 때와 같다.
기본적인 요소의 배치 순서에 따라 위에서 아래로, 왼쪽에서 오른쪽으로 순서에 따라 배치되며 부모 요소 내에 자식 요소로서 존재할 때는 부모 요소의 위치를 기준으로 배치
된다.
기본적으로 이 값을 지정할 일은 없지만 이미 설정된 position을 무력화하기 위해 사용될 수 있다. 좌표 프로퍼티(top
bottom
left
right
)를 같이 사용할 수 없으며 사용할 경우에는 무시된다.
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0; }
.parent {
width: 150px;
height: 150px;
background: #bcbcbc;
border: 1px solid #bcbcbc;
}
.static-box {
position: static;
background: #2E303D;
color: #e55c3c;
font-weight: bold;
text-align: center;
line-height: 150px;
}
</style>
</head>
<body>
<div class="parent">
<div class="static-box">static box</div>
</div>
</body>
</html>
기본 위치(static으로 지정되었을 때의 위치)를 기준으로 좌표 프로퍼티(
top
bottom
left
right
)를 사용하여 위치를 이동시킨다. static을 선언한 요소와 relative를 선언한 요소의 차이점은 좌표프로퍼티의 동작 여부
뿐이며 그외는 동일하게 동작한다.
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0; }
.parent {
width: 150px;
height: 150px;
background: #bcbcbc;
border: 1px solid #bcbcbc;
margin: 50px;
}
.relative-box {
position: relative;
top: 50px; left: 50px;
background: #2E303D;
color: #e55c3c;
font-weight: bold;
text-align: center;
line-height: 150px;
}
</style>
</head>
<body>
<div class="parent">
<div class="relative-box">relative box</div>
</div>
</body>
</html>
위 코드를 보면 parent 클래스의 자식인 relative-box 클래스 요소의 width
height
가 부모 요소와 동일하다.
이는 상속에 의한 것이 아니라 relative
를 적용한 요소는 좌표 프로퍼티가 적용되는 것만 다를 뿐 그 이외는 static
을 지정했을 때와 동일하게 동작하기 때문이다. 즉, width
는 100%
가 적용되어 부모 요소의 width와 동일
한 값을 갖게된 것이고, hight
는 auto
가 적용되지만 line-height: 150px
이 적용되어 부모 요소와 hight가 동일
하게 된 것이다.
부모 요소 또는 가장 가까이 있는 조상 요소(static 제외)를 기준으로 좌표 프로퍼티(
top
bottom
left
right
)만큼 이동한다. 즉,relative
absolute
fixed
프로퍼티가 선언되어 있는 부모 또는 조상 요소를 기준으로 위치가 결정된다.**
만일 부모 또는 조상 요소가 static인 경우, document body를 기준으로 하여 좌표 프로퍼티대로 위치하게 된다. 따라서 부모 요소를 배치의 기준으로 삼기 위해서는 부모 요소
에 relative
를 정의하여야 한다. 이때 다른 요소가 먼저 위치를 점유하고 있어도 뒤로 밀리지 않고 덮어쓰게 된다.
absolute
선언 시, block 레벨 요소의width
는 inline 요소와 같이content
에 맞게 변화되므로 적절한 width를 지정하여야 한다.
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0; }
.parent {
width: 200px;
height: 200px;
background: #bcbcbc;
border: 1px solid #bcbcbc;
margin: 50px 0 0 300px;
position: relative;
}
.absolute-box {
position: absolute;
height: 200px; width: 200px;
top: 50px; left: 50px;
color: #e55c3c;
font-weight: bold;
text-align: center;
background: #2E303D;
line-height: 200px;
}
</style>
</head>
<body>
<div class="parent">
<div class="absolute-box">absolute box (in parent)</div>
</div>
<div class="absolute-box">absolute box (no parent)</div></body>
</html>
relative 프로퍼티와 absolute 프로퍼티의 차이점
relative
프로퍼티는 기본 위치(static으로 지정되었을 때의 위치)를 기준으로 좌표 프로퍼티(top
bottom
left
right
)을 사용하여 위치를 이동시킨다.따라서 무조건 부모를 기준으로 위치
하게 된다.
absolute
프로퍼티는 부모에 static
이외의 position
프로퍼티가 지정되어 있을 경우에만 부모를 기준으로 위치
하게 된다. 만일 부모, 조상이 모두 static 프로퍼티인 경우, document body를 기준으로 위치하게 된다.
따라서 absolute 프로퍼티 요소는 부모 요소의 영역을 벗어나 자유롭게 어디든지 위치할 수 있다.
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0;}
.parent {
width: 150px;
height: 150px;
background: #bcbcbc;
border: 1px solid #bcbcbc;
margin: 50px;
float: left;
/*position: relative;*/
}
.relative-box {
position: relative;
top: 10px; left: 10px;
width: 150px;
height: 150px;
background: #2E303D;
color: #e55c3c;
font-weight: bold;
text-align: center;
line-height: 150px;
}
.absolute-box {
position: absolute;
top: 10px; left: 10px;
width: 150px;
height: 150px;
background: #2E303D;
color: #e55c3c;
font-weight: bold;
text-align: center;
line-height: 150px;
}
</style>
</head>
<body>
<div class="parent">
<div class="absolute-box">absolute box</div>
</div>
<div class="parent">
<div class="relative-box">relative box</div>
</div>
</body>
</html>
부모 요소와 관계없이 브라우저의 viewport를 기준으로 좌표프로퍼티(top, bottom, left, right)을 사용하여 위치를 이동시킨다. 스크롤이 되더라도 화면에서 사라지지 않고 항상 같은 곳에 위치한다.
fixed
프로퍼티 선언 시, block 요소의 width
는 inline 요소와 같이 content
에 맞게 변화되므로 적절한 width를 지정하여야 한다.**
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0; }
.fixed-box {
position: fixed;
color: #e55c3c;
font-weight: bold;
text-align: center;
background: #2E303D;
}
.sidebar {
width: 50px;
height: 100%;
top: 0;
right: 0;
padding-top: 100px;
}
.footer {
width: 200px;
width: 100%;
height: 50px;
bottom: 0;
left: 0;
line-height: 50px;
}
</style>
</head>
<body>
<div class="fixed-box sidebar">fixed box (side-bar)</div>
<div class="fixed-box footer">fixed box (footer)</div>
</body>
</html>
z-index 프로퍼티에 큰 숫자값을 지정할수록 화면 전면에 출력된다. positon 프로퍼티가 static 이외인 요소에만 적용된다.
<!DOCTYPE html>
<html>
<head>
<style>
.normal-box {
width: 100px; height: 100px;
}
.absolute-box {
width: 100px; height: 100px;
position: absolute;
}
/* z-index는 positon 프로퍼티가 static 이외인 요소에만 적용된다. */
.orange {
background-color: orange;
z-index: 1000;
}
.red {
background-color: red;
left: 50px; top: 50px;
z-index: 100;
}
.green {
background-color: green;
left: 100px; top: 100px;
z-index: 10;
}
.blue {
background-color: blue;
left: 150px; top: 150px;
z-index: 1;
}
</style>
</head>
<body>
<div class="normal-box orange"></div>
<div class="absolute-box red"></div>
<div class="absolute-box green"></div>
<div class="absolute-box blue"></div>
</body>
</html>
overflow 프로퍼티는 자식 요소가 부모 요소의 영역를 벗어났을 때 처리 방법을 정의한다.
프로퍼티값 | Description |
---|---|
visible | 영역을 벗어난 부분을 표시한다. (기본값) |
hidden | 영역을 벗어난 부분을 잘라내어 보이지 않게 한다. |
scroll | 영역을 벗어난 부분이 없어도 스크롤 표시한다.(현재 대부분 브라우저는 auto과 동일하게 작동한다) |
auto | 영역을 벗어난 부분이 있을때만 스크롤 표시한다. |
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 150px;
height: 150px;
padding: 10px;
margin: 30px;
font-size: 1.2em;
border-radius: 6px;
border-color: gray;
border-style: dotted;
float: left;
}
.visible { overflow: visible; }
.hidden { overflow: hidden; }
.scroll { overflow: scroll; }
.auto { overflow: auto; }
</style>
</head>
<body>
<h1>overflow</h1>
<div class="visible"><h3>visible</h3>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
<div class="hidden"><h3>hidden</h3>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
<div class="scroll"><h3>scroll</h3>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
<div class="auto"><h3>auto</h3>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
</body>
</html>
특정 방향으로만 스크롤을 표시하고자 할 때는 overflow-x 또는 overflow-y 프로퍼티를 사용한다.
div { overflow-y: auto; }
float
프로퍼티는 주로 레이아웃을 구성할 때 블록 레벨 요소를 가로 정렬하기 위해 사용되는 중요한 기법이다.
<!DOCTYPE html>
<html>
<head>
<style>
img {
float: left;
margin-right: 10px;
}
</style>
</head>
<body>
<img src="https://poiemaweb.com/img/doug.jpg">
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
</body>
</html>
float
프로퍼티는 해당 요소를 다음 요소 위에 떠 있게 한다. 여기서 떠 있다(float)는 의미는 요소가 기본 레이아웃 흐름에서 벗어나 요소의 모서리가 페이지의 왼쪽이나 오른쪽에 이동하는 것이다. float
프로퍼티를 사용할 때 요소의 위치를 고정시키는 position
프로퍼티의 absolute
를 사용하면 안된다.
프로퍼티값 | Description |
---|---|
none | 요소를 떠 있게 하지 않는다. (기본값) |
right | 요소를 오른쪽으로 이동시킨다 |
left | 요소를 왼쪽으로 이동시킨다. |
float
프로퍼티를 사용하지 않은 블록 요소들은 수직으로 정렬된다.
float:left;
프로퍼티를 사용하면 왼쪽부터 가로 정렬되고, float:right;
프로퍼티를 사용하면 오른쪽부터 가로 정렬된다. 오른쪽 가로 정렬의 경우, 먼저 기술된 요소가 가장 오른쪽에 출력
되므로 출력 순서가 역순
이 된다.
<!DOCTYPE html>
<html>
<head>
<style>
.box {
color: white;
font-weight: bold;
font-size: 50px;
border-radius: 6px;
width: 100px;
height: 100px;
margin: 10px;
padding: 10px;
}
.d1, .d2 {
float: left;
}
.d1 {
background: red;
}
.d2 {
background: orange;
}
.d3, .d4 {
float: right;
}
.d3 {
background: red;
}
.d4 {
background: orange;
}
</style>
</head>
<body>
<div class="container">
<div class="box d1"> 1 </div>
<div class="box d2"> 2 </div>
<div class="box d3"> 3 </div>
<div class="box d4"> 4 </div>
</div>
</body>
</html>
float
프로퍼티는 좌측, 우측 가로 정렬
만 할 수 있다. 중앙 가로 정렬
은 margin
프로퍼티를 사용해야 한다.
div {
width: 960px;
margin: 0 auto;
}
width 프로퍼티의 기본값은 100%이므로 width 프로퍼티값을 지정하지 않은
block 요소
는 부모 요소의 가로폭을 가득 채운다.
<!DOCTYPE html>
<html>
<head>
<style>
.box {
color: white;
font-weight: bold;
font-size: 30px;
line-height: 50px;
height: 50px;
margin: 0 10px;
padding: 10px;
}
.d1 {
background: red;
}
.d2 {
background: orange;
}
</style>
</head>
<body>
<div class="box d1"> div </div>
<div class="box d2"> div </div>
</body>
</html>
width
프로퍼티를 선언하지 않은 block 레벨 요소에 float 프로퍼티가 선언되면 width가 inline 요소와 같이 content에 맞게 최소화
되고 다음 요소 위에 떠 있게(부유하게) 된다.
<!DOCTYPE html>
<html>
<head>
<style>
.box {
color: white;
font-weight: bold;
font-size: 30px;
line-height: 50px;
height: 50px;
margin: 0 10px;
padding: 10px;
}
.d1 {
float: left;
background: red;
}
.d2 {
background: orange;
}
</style>
</head>
<body>
<div class="box d1"> float: left; </div>
<div class="box d2"> div </div>
</body>
</html>
d1 클래스 요소에는 float: left;
를 선언하였고 d2 클래스 요소에는 float
를 선언하지 않았다. 이때 d1 클래스 요소는 width가 inline 요소와 같이 content에 맞게 최소화
되고 다음 요소인 d2 클래스 요소 위에 떠 있게 된다.
주의할 것은 d1 클래스 요소가 d2 클래스 요소 위에 떠 있게 되어도 d2 클래스 요소의 width는 d1 클래스 요소가 차이한 width만큼 줄어들지 않고 100%를 유지한다는 것이다. 이는 d2 클래스 요소는 float를 선언하지 않았기 때문에 본래의 width를 유지하기 때문이다.
따라서 d2 클래스 요소는 본래의 width(100%)를 유지한 상태에서 d1 클래스 요소가 그 위에 위치한다.
두 요소는 차례대로 정렬된 것처럼 보이지만 사실은 float
프로퍼티가 선언된 요소가 다음 요소 위에 떠 있는 상태이다.따라서 두 요소간의margin
은 제대로 표현되지 않는다. 두번째 요소에 float
프로퍼티를 선언하지 않았기 때문에 발생하는 박스 모델 상의 문제이다.
이 문제를 해결하는 가장 쉬운 방법은 float
프로퍼티를 선언하지 않은 요소(.d2)에 overflow: hidden
프로퍼티를 선언하는 것이다.
overflow: hidden
프로퍼티는 자식 요소가 부모 요소의 영역보다 클 경우 넘치는 부분을 안보이게 해주는 역할을 하는데 여기서는 float
프로퍼티가 없어서 제대로 표현되지 못하는 요소를 제대로 출력해준다.
<!DOCTYPE html>
<html>
<head>
<style>
.box {
color: white;
font-weight: bold;
font-size: 30px;
line-height: 50px;
height: 50px;
margin: 0 10px;
padding: 10px;
}
.d1 {
float: left;
background: red;
}
.d2 {
overflow: hidden;
background: orange;
}
</style>
</head>
<body>
<div class="box d1"> float: left; </div>
<div class="box d2"> div </div>
</body>
</html>
두번째 요소에도
float
프로퍼티를 선언하면overflow: hidden
프로퍼티는 선언하지 않아도 되지만너비가 최소화
된다.
float
요소는 일반적인 흐름 상에 존재하지 않기 때문에 float
프로퍼티가 선언된 두개의 자식 요소를 포함하는 부모 요소의 높이가 정상적인 값을 가지지 못하는 문제가 발생한다. 이는 float 요소의 높이
를 알 수 없기 때문인데 이 문제는 부모 요소 이후에 위치하는 요소의 정렬
에 문제를 발생시킨다.
<!DOCTYPE html>
<head>
<style>
.container {
color: white;
text-align: center;
padding: 10px;
background-color: #def0c2;
}
.d1, .d2 {
float: left;
width: 50%;
padding: 20px 0;
}
.d1 {
background-color: #59b1f6;
}
.d2 {
background-color: #ffb5b4;
}
</style>
</head>
<body>
<div class="container">
<div class="d1">1</div>
<div class="d2">2</div>
</div>
<div style="background:red;padding:10px;color:white;">3</div>
</body>
</html>
이 문제를 해결하는 가장 쉬운 방법은
float
프로퍼티가 선언된 자식 요소의 부모 요소에overflow: hidden
프로퍼티를 선언하는 것이다.
.container {
...
overflow: hidden;
}
다른 방법으로 부모 요소에
float
프로퍼티를 선언하는 방법도 있다. 하지만 부모 요소의 너비는float
된 두개의 자식요소의 콘텐츠를 표현할 수 있는 만큼만으로 작게 줄어들게 된다. 권장할 수 있는 방법은 아니다.
container 영역이 끝나기 직전 빈 요소를 만들고
clear:both
를 설정하는 방법도 가능하다. 하지만 의미 없는 빈 요소를 사용하여야 하기 때문에 이 방법 역시 권장할 수 있는 방법은 아니다.
<!DOCTYPE html>
<html>
<head>
<style>
.container {
color: white;
text-align: center;
padding: 10px;
background-color: #def0c2;
/*overflow: hidden;*/
}
.d1, .d2 {
float: left;
width: 50%;
padding: 20px 0;
}
.d1 {
background-color: #59b1f6;
}
.d2 {
background-color: #ffb5b4;
}
.clear {
height: 0;
clear: both;
}
</style>
</head>
<body>
<div class="container">
<div class="d1">1</div>
<div class="d2">2</div>
<div class="clear"></div>
</div>
<div style="background:red; padding:10px; color:white;">3</div>
</body>
</html>
overflow: hidden;
과 함께 많이 사용되는 방법은::after 가상 요소 선택자
를 이용하는 것이다.
<!DOCTYPE html>
<html>
<head>
<style>
.container {
color: white;
text-align: center;
padding: 10px;
background-color: #def0c2;
/*overflow: hidden;*/
}
.clearfix:after {
content: "";
display: block;
clear: both;
}
.d1, .d2 {
float: left;
width: 50%;
padding: 20px 0;
}
.d1 {
background-color: #59b1f6;
}
.d2 {
background-color: #ffb5b4;
}
</style>
</head>
<body>
<div class="container clearfix">
<div class="d1">1</div>
<div class="d2">2</div>
</div>
<div style="background:red;padding:10px;color:white;">3</div>
</body>
</html>
부모 요소에 위 예제와 같이 사전에 작성한 clearfix 클래스만 추가하거나, 해당 요소를 선택하여 클리어 문법을 선언하면 되기 때문에 가장 깔끔하고 간편하다.
.clearfix:after {
content: "";
display: block;
clear: both;
}
/* or */
selector:after {
content: "";
display: block;
clear: both;
}
또 다른 방법은 float
프로퍼티 대신 display: inline-block;
을 선언하는 것이다. 주의해야야 점은 inline-block 프로퍼티 요소를 연속 사용하는 경우, 두 요소 사이에 정의하지 않은 공백(4px)가 자동 지정
되는 것이다.
<!DOCTYPE html>
<html>
<head>
<style>
.container {
color: white;
text-align: center;
padding: 10px;
background-color: #def0c2;
}
.d1, .d2 {
display: inline-block;
width: 50%;
padding: 20px 0;
}
.d1 {
background-color: #59b1f6;
}
.d2 {
background-color: #ffb5b4;
}
</style>
</head>
<body>
<div class="container">
<div class="d1">1</div>
<div class="d2">2</div>
</div>
<div style="background:red;padding:10px;color:white;">3</div>
</body>
</html>
.d1, .d2 요소에 display: inline-block;
을 선언하여 텍스트와 같이 배치되도록 하였지만, 두 요소 사이에 정의하지 않은 공백(4px)이 자동 지정
되어 부모 요소의 width를 초과
하여 가로 정렬이 되지 않았다.
이 현상을 회피하기 위해 부모 요소에 font-size: 0;
을 선언하여 두 요소 사이에 정의하지 않은 공백을 제거한다.
<!DOCTYPE html>
<html>
<head>
<style>
.container {
color: white;
text-align: center;
padding: 10px;
background-color: #def0c2;
/* 폰트 사이즈를 0으로 지정하여 두 요소 사이에 정의하지 않은 공백을 제거 */
font-size: 0;
}
.d1, .d2 {
display: inline-block;
width: 50%;
padding: 20px 0;
/* 폰트 사이즈를 재지정 */
font-size: 1rem;
}
.d1 {
background-color: #59b1f6;
}
.d2 {
background-color: #ffb5b4;
}
</style>
</head>
<body>
<div class="container">
<div class="d1">1</div>
<div class="d2">2</div>
</div>
<div style="background:red;padding:10px;color:white;">3</div>
</body>
</html>
상속
이란 상위(부모, 조상) 요소에 적용된 프로퍼티를 하위(자식, 자손) 요소가 물려 받는 것을 의미한다. 상속 기능이 없다면 각 요소의 Rule set에 프로퍼티를 매번 각각 지정해야 한다. 하지만 모든 프로퍼티가 상속되는 것은 아니다. 프로퍼티 중에는 상속이 되는 것과 되지 않는 것이 있다.
Property | Inherit |
---|---|
width / height | no |
margin | no |
padding | no |
border | no |
box-sizing | no |
display | no |
visibility | yes |
opacity | yes |
background | no |
font | yes |
color | yes |
line-height | yes |
text-align | yes |
vertical-align | no |
text-decoration | no |
white-space | yes |
position | no |
top/right/bottom/left | no |
z-index | no |
overflow | no |
float | no |
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
.text-red {
color: red;
border: 1px solid #bcbcbc;
padding: 10px;
}
</style>
</head>
<body>
<div class="text-red">
<h1>Heading</h1>
<p>Paragraph<strong>strong</strong></p>
<button>Button</button>
</div>
</body>
</html>
color
는 상속되는 프로퍼티로서 자식 요소는 물론 자손 요소까지 적용된다. 하지만 button
처럼 요소에 따라 상속 받지 않는 경우도 존재한다. border
padding
은 상속되지 않는 요소로 하위 요소에 적용되지 않는다.
상속되지 않는 경우(상속받지 않는 요소 또는 상속되지 않는 프로퍼티), inherit
키워드를 사용하여 명시적으로 상속받게 할 수 있다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
.text-red {
color: red;
border: 1px solid #bcbcbc;
padding: 10px;
}
.text-red button {
color: inherit;
}
.text-red p {
border: inherit;
padding: inherit;
}
</style>
</head>
<body>
<div class="text-red">
<h1>Heading</h1>
<p>Paragraph<strong>strong</strong></p>
<button>Button</button>
</div>
</body>
</html>
요소는 하나 이상의 CSS 선언에 영향을 받을 수 있다. 이때 충돌을 피하기 위해 CSS 적용 우선순위
가 필요한데 이를 캐스캐이딩(Cascading Order)
이라고 한다. 캐스캐이딩에는 다음과 같이 세가지 규칙이 있다.
중요도
CSS가어디에 선언 되었는지
에 따라서 우선순위가 달라진다.
명시도
대상을명확하게 특정
할수록 명시도가 높아지고 우선순위가 높아진다.
선언순서
선언된 순서
에 따라 우선 순위가 적용된다. 즉, 나중에 선언된 스타일이 우선 적용된다.
CSS가 어디에 선언 되었는지에 따라서 우선순위가 달라진다.
@import
문<link>
로 연결된 CSS 파일<link>
로 연결된 CSS 파일 내의 @import
문/* style.css */
body {
background-color: red;
color: white;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<style>
body {
background-color: beige;
color: navy;
}
</style>
</head>
<body>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</body>
</html>
대상을 명확하게 특정할수록 명시도가 높아지고 우선순위가 높아진다.
!important > 인라인 스타일 > 아이디 선택자 > 클래스/어트리뷰트/가상 선택자 > 태그 선택자 > 전체 선택자 > 상위 요소에 의해 상속된 속성
<!DOCTYPE html>
<html>
<head>
<style>
p { color: red !important; }
#thing { color: blue; }
div.food { color: chocolate; }
.food { color: green; }
div { color: orange; }
</style>
</head>
<body>
<p id="thing">Will be Red.</p>
<div class="food">Will be Chocolate.</div>
</body>
</html>
선언된 순서에 따라 우선 순위가 적용된다. 즉, 나중에 선언된 스타일이 우선 적용된다.
<!DOCTYPE html>
<html>
<head>
<style>
p { color: blue; }
p { color: red; }
.red { color: red; }
.blue { color: blue; }
</style>
</head>
<body>
<p>Will be RED.</p>
<p class="blue red">Will be BLUE.</p>
</body>
</html>
CSS3 표준으로 확정되기 이전 또는 브라우저 개발사가 실험적으로 제공하는 기능을 사용하기 위해서는 벤더 프리픽스(Vendor Prefix)
를 사용하여야 한다. Can I use?에서 제공하는 브라우저별 CSS 지원 정보를 보면 텍스트와 요소의 선택을 방지하는 user-select
프로퍼티는 모든 브라우저에 벤더 프리픽스를 사용하여야 한다. 브라우저의 버전이 올라감에 따라 벤더 프리픽스를 사용하지 않아도 될 수 있다. 그러나 구형 브라우저를 지원하기 위하여 벤더 프리픽스를 사용하여야 할 필요가 있다.
2022년 8월 기준
모든 요소에 user-select 벤더프리픽스를 사용 한 경우, 브라우저에 맞는 속성만 적용됐다.
* {
-webkit-user-select: none; /* Chrome all / Safari all */
-moz-user-select: none; /* Firefox all */
user-select: none; /* Likely future */
}
브라우저 별 벤더 프리픽스
Browser | Vendor Prefix |
---|---|
IE or Edge | -ms- |
Chrome | -webkit- |
Firefox | -moz- |
Safari | -webkit- |
Opera | -o- |
iOS Safari | -webkit- |
Android Browser | -webkit- |
Chrome for Android | -webkit- |
많은 브라우저를 위한 벤더 프리픽스를 사용하는 것은 코드의 양
을 늘게 하고 또한 브라우저는 거의 매달 업데이트가 이루어지고 있어 불필요한 벤더 프리픽스를 사용할 가능성이 크다. 사용하지 않아도 되는 벤더 프리픽스를 사용하는 것은 성능
에도 영향을 주기 때문에 Prefix Free 라이브러리 를 사용하는 것은 매우 유용한 방법이다.
Prefix Free 사이트에서 라이브러리를 다운로드하고 include 하기만 하면 이 후에는 벤더 프리픽스없이 모든 CSS를 사용할 수 있다.
<script src="prefixfree.min.js"></script>
텍스트에 그림자 효과를 부여하는 프로퍼티이다.
선택자 { text-shadow: Horizontal-offset Vertical-offset Blur-Radius Shadow-Color; }
프로퍼티 값 | 단위 | 설명 | 생략 |
---|---|---|---|
Horizontal-offset | px | 그림자를 텍스트의 오른쪽으로 지정값만큼 이동시킨다 | |
Vertical-offset | px | 그림자를 텍스트의 아래로 지정값만큼 이동시킨다 | |
Blur-Radius | px | 그림자의 흐림정도를 지정한다. 지정값만큼 그림자가 커지고 흐려진다. (양수) | 가능 |
Shadow-Color | color | 그림자의 색상을 지정한다 | 가능 |
<!DOCTYPE html>
<html>
<head>
<style>
h1:nth-child(1) {
text-shadow: 5px 5px;
}
h1:nth-child(2) {
text-shadow: 5px 5px red;
}
h1:nth-child(3) {
text-shadow: 5px 5px 3px red;
}
h1:nth-child(4) {
color: white;
text-shadow: 5px 5px 3px black;
}
h1:nth-child(5) {
text-shadow: 0 0 3px red;
}
/*Multiple Shadows*/
h1:nth-child(6) {
text-shadow: 0 0 3px red, 0 0 10px blue;
}
/*Multiple Shadows*/
h1:nth-child(7) {
color: white;
text-shadow: 1px 1px 2px black, 0 0 25px blue, 0 0 5px darkblue;
}
</style>
</head>
<body>
<h1>Text-shadow effect!</h1>
<h1>Text-shadow effect!</h1>
<h1>Text-shadow effect!</h1>
<h1>Text-shadow effect!</h1>
<h1>Text-shadow effect!</h1>
<h1>Text-shadow effect!</h1>
<h1>Text-shadow effect!</h1>
</body>
</html>
Property | Chrome | Edge | IE | Firefox | Safari | Opera |
---|---|---|---|---|---|---|
text-shadow | 4 | 12 | 10 | 3.5 | 4 | 9.5 |
요소에 그림자 효과를 부여하는 프로퍼티이다.
선택자 { box-shadow: Inset Horizontal-offset Vertical-offset Blur-Radius Spread Shadow-Color; }
프로퍼티 값 | 단위 | 설명 | 생략 |
---|---|---|---|
Inset | inset | inset 키워드를 지정하면 그림자가 요소 안쪽에 위치한다. | 가능 |
Horizontal-offset | px | 그림자를 텍스트의 오른쪽으로 지정값만큼 이동시킨다 | |
Vertical-offset | px | 그림자를 텍스트의 아래로 지정값만큼 이동시킨다 | |
Blur-Radius | px | 그림자의 흐림정도를 지정한다. 지정값만큼 그림자가 커지고 흐려진다. (양수) | 가능 |
Spread | px | 그림자를 더 크게 확장시킨다. (음수, 양수) | 가능 |
Shadow-Color | color | 그림자의 색상을 지정한다 | 가능 |
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 300px;
height: 100px;
padding: 15px;
margin: 20px;
background-color: yellow;
}
/*box-shadow: Inset Horizontal-offset Vertical-offset Blur-Radius Spread Shadow-Color;*/
/* Horizontal-offset Vertical-offset */
div:nth-of-type(1) {
box-shadow: 10px 10px;
}
/* Horizontal-offset Vertical-offset Shadow-Color */
div:nth-of-type(2) {
box-shadow: 10px 10px blue;
}
/* Horizontal-offset Vertical-offset Blur-Radius Shadow-Color */
div:nth-of-type(3) {
box-shadow: 10px 10px 5px blue;
}
/* Horizontal-offset Vertical-offset Blur-Radius Spread Shadow-Color */
div:nth-of-type(4) {
box-shadow: 10px 10px 5px 5px blue;
}
/* Inset Horizontal-offset Vertical-offset Blur-Radius Spread Shadow-Color */
div:nth-of-type(5) {
box-shadow: inset 10px 10px 5px 5px blue;
}
/* Horizontal-offset Vertical-offset Blur-Radius Spread Shadow-Color */
div:nth-of-type(6) {
background-color: white;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
</style>
</head>
<body>
<div>This is a div element with a box-shadow</div>
<div>This is a div element with a box-shadow</div>
<div>This is a div element with a box-shadow</div>
<div>This is a div element with a box-shadow</div>
<div>This is a div element with a box-shadow</div>
<div>This is a div element with a box-shadow</div>
</body>
</html>
그레이디언트(Gradient)는 2가지 이상의 색상을 혼합하여 부드러운 색감의 배경 등을 생성하는 것이다.
CSS3가 이 기능을 제공하기 이전에는 포토샵 등의 소프트웨어를 사용하여 그레이디언트 효과의 이미지를 제작하여 사용하였다. 그러나 이러한 방법은 이미지 다운로드
에 시간이 소요되는 문제와 이미지를 확대하였을 때 해상도
가 나빠지는 문제 등을 내포하고 있었다.
그레이디언트는 2가지 종류가 있다.
대부분의 브라우저에 벤더프리픽스를 사용하여야 하고 브라우저에 따라 조금씩 문법이 상이하여 다루기가 수월하지 않다. 따라서 그레이디언트를 직접 작성하는 것보다 작성 툴을 이용하는 것이 보편적이다.
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
}
div {
width: 100vw;
height: 100vh;
}
.dawn {
/* Old browsers */
background: #b3cae5;
/* FF3.6+ */
background: -moz-linear-gradient(-45deg, #b3cae5 12%, #dbdde4 46%, #e4e3e4 70%, #f7ddbb 94%, #efcab2 100%);
/* Chrome,Safari4+ */
background: -webkit-gradient(linear, left top, right bottom, color-stop(12%, #b3cae5), color-stop(46%, #dbdde4), color-stop(70%, #e4e3e4), color-stop(94%, #f7ddbb), color-stop(100%, #efcab2));
/* Chrome10+,Safari5.1+ */
background: -webkit-linear-gradient(-45deg, #b3cae5 12%, #dbdde4 46%, #e4e3e4 70%, #f7ddbb 94%, #efcab2 100%);
/* Opera 11.10+ */
background: -o-linear-gradient(-45deg, #b3cae5 12%, #dbdde4 46%, #e4e3e4 70%, #f7ddbb 94%, #efcab2 100%);
/* IE10+ */
background: -ms-linear-gradient(-45deg, #b3cae5 12%, #dbdde4 46%, #e4e3e4 70%, #f7ddbb 94%, #efcab2 100%);
/* W3C */
background: linear-gradient(135deg, #b3cae5 12%, #dbdde4 46%, #e4e3e4 70%, #f7ddbb 94%, #efcab2 100%);
}
</style>
</head>
<body>
<div class="dawn"></div>
</body>
</html>
트랜지션(transition)은 CSS 프로퍼티의 값이 변화할 때, 프로퍼티 값의 변화가
일정 시간(duration)
에 걸쳐 일어나도록 하는 것이다.
div 요소는 기본 상태에서 hover 상태로 변화할 때, CSS 프로퍼티 border-radius와 background 프로퍼티의 값이 변화한다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 100px;
background: red;
}
div:hover {
border-radius: 50%;
background: blue;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
상태 변화에 따라 CSS 프로퍼티가 변경되면 프로퍼티 변경에 따른
표시의 변화(transition)는 지체없이 즉시 발생
한다.
트랜지션(transition)은 상태 변화에 동반하여 변경되는 CSS 프로퍼티 값에 의한 표시의 변화를 부드럽게 하기 위해 애니메이션 속도를 조절한다. 즉, 프로퍼티 값의 변경이 표시의 변화에 즉시 영향을 미치게 하는 대신 그 프로퍼티 값의 변화가 일정 시간(duration)
에 걸쳐 일어나도록 하는 것이다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 100px;
background: red;
/* 트랜지션 효과: 모든 프로퍼티의 변화를 2초에 걸쳐 전환한다. */
transition: all 2s;
}
div:hover {
border-radius: 50%;
background: blue;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
div 셀렉터의 룰셋
에 트랜지션을 설정하면 마우스가 올라갈 때(hover on)와 마우스가 내려올 때(hover off) 모두 트랜지션이 발동한다. 하지만div:hover 셀렉터의 룰셋
에 트랜지션을 설정하면 마우스가 올라갈 때(hover on)는 트랜지션이 발동하지만 마우스가 내려올 때(hover off)는 트랜지션이 발동하지 않는다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 100px;
background: red;
}
div:hover {
background: blue;
border-radius: 50%;
/* hover on에서만 발동한다. */
transition: all 2s;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
transition은 자동으로 발동되지 않는다.
:hover
와 같은가상 클래스 선택자
또는JavaScript
의 부수적인 액션에 의해 발동한다.
transition의 프로퍼티는 아래와 같다.
프로퍼티 | 설명 | 기본값 |
---|---|---|
transition-property | 트랜지션의 대상이 되는 CSS 프로퍼티를 지정한다 | all |
transition-duration | 트랜지션이 일어나는 지속시간(duration)을 초 단위(s) 또는 밀리 초 단위(ms)로 지정한다 | 0s |
transition-timing-function | 트랜지션 효과를 위한 수치 함수를 지정한다. | ease |
transition-delay | 프로퍼티가 변화한 시점과 트랜지션이 실제로 시작하는 사이에 대기하는 시간을 초 단위(s) 또는 밀리 초 단위(ms)로 지정한다 | 0s |
transition | 모든 트랜지션 프로퍼티를 한번에 지정한다 (shorthand syntax) |
transition-property 프로퍼티는 트랜지션의 대상이 되는 CSS 프로퍼티명을 지정한다.
지정하지 않는 경우 모든 프로퍼티가 트랜지션의 대상이 된다. 복수의 프로퍼티를 지정하는 경우 쉼표(,)
로 구분한다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 50px;
background-color: red;
margin-bottom: 10px;
transition-property: width, background-color;
transition-duration: 2s, 2s;
}
div:hover {
width: 300px;
background-color: blue;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
주의해야 할 사항은 모든 CSS 프로퍼티가 트랜지션의 대상이 될 수 없다는 것이다. 트랜지션의 대상이 될 수 있는 CSS 프로퍼티는 아래와 같다.
Box model
width height max-width max-height min-width min-height
padding margin
border-color border-width border-spacing
Background
background-color background-position
좌표
top left right bottom
텍스트
color font-size font-weight letter-spacing line-height
text-indent text-shadow vertical-align word-spacing
기타
opacity outline-color outline-offset outline-width
visibility z-index
또한 요소의 프로퍼티 값이 변화하면 브라우저는 프로퍼티 값의 변화에 영향을 받는 모든 요소의 기하값(위치와 크기)를 계산하여 layout 작업을 수행한다.이것은 브라우저에게 스트레스를 주어 성능 저하의 요인이 된다. 심지어 다수의 자식 요소를 가지고 있는 요소(예를 들어 body 요소)가 변경되면 모든 자식 요소의 기하값이 재계산될 수도 있다.따라서 layout에 영향을 주는 트랜지션 효과는 회피하도록 노력해야 한다.
layout에 영향을 주는 프로퍼티는 아래와 같다.
transition-duration
프로퍼티는 트랜지션에 일어나는지속시간(duration)
을초 단위(s)
또는밀리 초 단위(ms)
로 지정한다. 프로퍼티값을 지정하지 않을 경우 기본값 0s이 적용되어 어떠한 트랜지션 효과도 볼 수 없다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 50px;
padding: 10px;
color: white;
background-color: red;
margin-bottom: 10px;
transition-property: width, opacity;
}
div:nth-child(1) {
transition-duration: 0.5s;
}
div:nth-child(2) {
transition-duration: 2s, 1s;
}
div:nth-child(3) {
transition-duration: 5s, 2.5s;
}
div:hover {
width: 300px;
opacity: .1;
}
</style>
</head>
<body>
<div>0.5s</div>
<div>2s, 1s</div>
<div>5s, 2.5s</div>
</body>
</html>
transition-duration 프로퍼티값은 transition-property 프로퍼티값과 1:1 대응한다.
ex1) width 프로퍼티는 2초의 지속시간을 갖는다(2초에 걸쳐 변화한다).
div {
transition-property: width;
transition-duration: 2s;
}
ex2) width 프로퍼티는 2초, opacity 프로퍼티는 4초의 지속시간을 갖는다.
div {
transition-property: width, opacity;
transition-duration: 2s, 4s;
}
ex3) transition 프로퍼티만으로 축약 표현이 가능하다.
div {
/* shorthand syntax */
transition: width 2s, opacity 4s;
}
ex4) width 프로퍼티는 2초, opacity 프로퍼티는 1초, left 프로퍼티는 2초, top 프로퍼티는 1초의 지속시간을 갖는다.
div {
transition-property: width, opacity, left, top;
transition-duration: 2s, 1s;
}
트랜지션 효과의 변화 흐름, 시간에 따른 변화 속도와 같은 일종의 변화의 리듬을 지정한다.
대부분의 타이밍 함수는 큐빅 베이지어(cubic bezier)
를 정의하는 네 점에 의해 정의되므로 상응하는 함수의 그래프로 제공해서 명시할 수 있다. transition-timing-function
프로퍼티값으로 미리 정해둔 5개의 키워드가 제공된다. 기본값은 ease
이다.
프로퍼티값 | 효과 |
---|---|
ease | 기본값. 느리게 시작하여 점점 빨라졌다가 느려지면서 종료한다. |
linear | 시작부터 종료까지 등속 운동을 한다 |
ease-in | 느리게 시작한 수 일정한 속도에 다다르면 그 상태로 등속 운동한다. |
ease-out | 일정한 속도의 등속으로 시작해서 점점 느려지면서 종료한다. |
ease-in-out | ease와 비슷하게 느리게 시작하여 느려지면서 종료한다. |
<!DOCTYPE html>
<html>
<head>
<style>
div {
font: bold 16px/50px "Open Sans";
color: white;
text-align: center;
width: 100px;
height: 50px;
background-color: red;
margin-bottom: 10px;
transition: width 2s;
}
div:nth-child(1) {
transition-timing-function: ease;
}
div:nth-child(2) {
transition-timing-function: linear;
}
div:nth-child(3) {
transition-timing-function: ease-in;
}
div:nth-child(4) {
transition-timing-function: ease-out;
}
div:nth-child(5) {
transition-timing-function: ease-in-out;
}
div:hover {
width: 300px;
}
</style>
</head>
<body>
<h3>transition-timing-function</h3>
<div>ease</div>
<div>linear</div>
<div>ease-in</div>
<div>ease-out</div>
<div>ease-in-out</div>
</body>
</html>
프로퍼티가 변화한 시점과 트랜지션이 실제로 시작하는 사이에
대기하는 시간
을초 단위(s)
또는밀리 초 단위(ms)
로 지정한다. 즉, transition-delay로대기 시간
을 지정하여 프로퍼티의 값이 변화하여도 즉시 트랜지션이 실행되지 않고,일정 시간 대기
한 후 트랜지션이 실행되도록 한다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
font: bold 16px/50px "Open Sans";
color: white;
text-align: center;
width: 100px;
height: 50px;
background-color: red;
margin-bottom: 10px;
transition: width 1s;
}
div:nth-of-type(1) {
transition-delay: 0s;
}
div:nth-of-type(2) {
transition-delay: 1s;
}
div:nth-of-type(3) {
transition-delay: 3s;
}
div:hover {
width: 300px;
}
</style>
</head>
<body>
<h3>transition-delay</h3>
<div>0s</div>
<div>1s</div>
<div>3s</div>
</body>
</html>
모든 트랜지션 프로퍼티를 한번에 지정할 수 있는 shorthand이다. 값을 지정하지 않은 프로퍼티에는 기본값이 지정된다.
transition-duration
은 반드시 지정해야 한다. 지정하지 않는 경우 기본값 0이 셋팅되어 어떠한 트랜지션도 실행되지 않는다.
transition: property duration function delay
// 기본값
transition: all 0 ease 0
<!DOCTYPE html>
<html>
<head>
<style>
div {
font: bold 0.5em/50px "Open Sans";
color: white;
text-align: center;
width: 100px;
height: 50px;
margin-bottom: 10px;
background-color: red;
}
div:nth-of-type(1) {
/* property duration function delay */
transition: width 1s ease-in 1s;
}
div:nth-of-type(2) {
/* duration */
transition: 1s
}
div:nth-of-type(3) {
/* property duration */
transition: width 1s
}
div:nth-of-type(4) {
/* duration function */
transition: 1s ease-in;
}
div:nth-of-type(5) {
/* duration delay*/
transition: 1s 1s;
}
div:hover {
width: 300px;
}
</style>
</head>
<body>
<div>width 1s ease-in 1s</div>
<div>1s</div>
<div>width 1s</div>
<div>1s ease-in</div>
<div>1s 1s</div>
</body>
</html>
애니메이션(Animation) 효과는 HTML 요소에 적용되는 CSS 스타일을 다른 CSS 스타일로 부드럽게 변화시킨다.
애니메이션은 애니메이션을 나타내는 CSS 스타일과 애니메이션의 sequence를 나타내는 복수의 키프레임(@keyframes
) 들로 이루어진다. transition
으로도 어느 정도의 애니메이션 효과를 표현할 수 있으나 animation
보다는 제한적이다.
일반적으로 CSS 애니메이션을 사용하면 기존의 JavaScript 기반 애니메이션
실행과 비교하여 더 나은 렌더링 성능
을 제공한다고 알려져 있다. 그러나 경우에 따라서는 JavaScript
를 사용하는 것이 나을 수도 있다. jQuery 등의 애니메이션 기능은 CSS보다 간편하게 애니메이션 효과를 가능케 한다.
width 변경
애니메이션은 자바스크립트를 사용하는 것보다 훨씬 간편하며 효과적이다.바운스
중지
일시 중지
되감기
감속
과 같은 고급 효과는 자바스크립트가 훨씬 유용하다.가장 중요한 것은 브라우저에서 애니메이션 효과가
부드럽게 실행
되는 것이다. 그리고 애니메이션 효과 작성에 소요되는 시간과 수고이다. 여러 사항들을 고려하여 자바스크립트를 사용하여야 할지 CSS를 사용하여야 할지 결정하여야 한다.
프로퍼티 | 설명 | 기본값 |
---|---|---|
animation-name | @keyframes 애니메이션 이름을 지정한다 | |
animation-duration | 한 싸이클의 애니메이션에 소요되는 시간을 초 단위(s) 또는 밀리 초 단위(ms)로 지정한다. | 0s |
animation-timing-function | 애니메이션 효과를 위한 타이밍 함수를 지정한다. | ease |
animation-delay | 요소가 로드된 시점과 애니메이션이 실제로 시작하는 사이에 대기하는 시간을 초 단위(s) 또는 밀리 초 단위(ms)로 지정한다 | 0s |
animation-iteration-count | 애니메이션 재생 횟수를 지정한다. | 1 |
animation-direction | 애니메이션이 종료된 이후 반복될 때 진행하는 방향을 지정한다. | normal |
animation-fill-mode | 애니메이션 미실행 시(종료 또는 대기) 요소의 스타일을 지정한다. | |
animation-play-state | 애니메이션 재생 상태(재생 또는 중지)를 지정한다. | running |
animation | 모든 애니메이션 프로퍼티를 한번에 지정한다 (shorthand syntax) |
CSS 애니메이션과 트랜지션 방식의 주된 차이는 @keyframes rule
에 있다. 이 rule을 사용하면 애니메이션의 흐름 중의 여러 시점(breakpoint)
에서 CSS 프로퍼티값을 지정할 수 있다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
position: absolute;
width: 100px;
height: 100px;
background-color: red;
animation-name: move;
animation-duration: 5s;
animation-iteration-count: infinite;
}
/* @keyframes rule */
@keyframes move {
/* keyframe */
from {
left: 0;
}
/* keyframe */
to {
left: 300px;
}
}
</style>
</head>
<body>
<div></div>
</body>
</html>
@keyframes rule
은 시간의 흐름에 따라 애니메이션을 정의한다.
여러 개의 키프레임을 정의하거나 애니메이션 중에 특정 CSS 프로퍼티에 값을 지정하는 지점을 정의할 수 있다.
@keyframes 뒤에 애니메이션을 대표하는 임의의 이름
을 부여한다.
@keyframes move {}
시작
과 끝
키프레임 사이에 % 단위로 키프레임
을 삽입할 수 있다.
@keyframes move {
0% { left: 0; }
50% { left: 100px; }
100% { left: 300px; }
}
이름을
animation-name
프로퍼티값으로 지정하여 사용하고자 하는@keyframes rule
을 선택한다. 하나 이상의 애니메이션 이름을 지정할 수 있다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
position: absolute;
width: 100px;
height: 100px;
animation-name: move, fadeOut, changeColor;
animation-duration: 5s;
animation-iteration-count: infinite;
}
@keyframes move {
from { left: 0; }
to { left: 300px; }
}
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
@keyframes changeColor {
from { background-color: red; }
to { background-color: blue; }
}
</style>
</head>
<body>
<div></div>
</body>
</html>
한 싸이클의 애니메이션에
소요되는 시간
을초 단위(s)
또는밀리 초 단위(ms)
로 지정한다.
animation-duration은 반드시 지정해야 한다. 지정하지 않는 경우 기본값 0s가 셋팅되어 어떠한 애니메이션도 실행되지 않는다.
animation-duration: .5s;
animation-duration: 500ms;
애니메이션 효과를 위한 수치 함수를 지정한다. 수치 함수는 CSS의 transition효과와 동일하다.
요소가
로드된 시점
과 애니메이션이실제로 시작하는 사이에 대기하는 시간
을초 단위(s)
또는밀리 초 단위(ms)
로 지정한다.
animation-delay: 2s;
애니메이션 주기의 재생 횟수를 지정한다. 기본값은 1이며 infinite로 무한반복 할 수 있다.
animation-iteration-count: 3;
애니메이션이 종료된 이후 반복될 때 진행하는 방향을 지정한다.
프로퍼티값 | 설명 |
---|---|
normal | 기본값으로 from(0%)에서 to(100%) 방향으로 진행한다. |
reverse | to에서 from 방향으로 진행한다. |
alternate | 홀수번째는 normal로, 짝수번째는 reverse로 진행한다. |
alternate-reverse | 홀수번째는 reverse로, 짝수번째는 normal로 진행한다. |
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 100px;
background: red;
position: relative;
animation: myAnimation 5s infinite;
/*홀수번째는 normal로, 짝수번째는 reverse로 진행*/
animation-direction: alternate;
}
@keyframes myAnimation {
0% { background: red; left: 0px; top: 0px; }
25% { background: yellow; left: 200px; top: 0px; }
50% { background: blue; left: 200px; top: 200px; }
75% { background: green; left: 0px; top: 200px; }
100% { background: red; left: 0px; top: 0px; }
}
</style>
</head>
<body>
<div></div>
</body>
</html>
애니메이션 미실행 시(대기 또는 종료) 요소의 스타일을 지정한다.
프로퍼티값 | 상태 | 설명 |
---|---|---|
none | 대기 | 시작 프레임(from)에 설정한 스타일을 적용하지 않고 대기한다. |
종료 | 애니메이션 실행 전 상태로 애니메이션 요소의 프로퍼티값을 되돌리고 종료한다. | |
forwards | 대기 | 시작 프레임(from)에 설정한 스타일을 적용하지 않고 대기한다. |
종료 | 종료 프레임(to)에 설정한 스타일을 적용하고 종료한다. | |
backwards | 대기 | 시작 프레임(from)에 설정한 스타일을 적용하고 대기한다. |
종료 | 애니메이션 실행 전 상태로 애니메이션 요소의 프로퍼티값을 되돌리고 종료한다. | |
both | 대기 | 시작 프레임(from)에 설정한 스타일을 적용하고 대기한다. |
종료 | 종료 프레임(to)에 설정한 스타일을 적용하고 종료한다. |
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 100px;
font: bold 1em/100px san-serif;
text-align: center;
color: #fff;
background: red;
margin-bottom: 10px;
position: relative;
/*name duration timing-function delay iteration-count direction fill-mode play-state*/
animation: myAnimation 2s linear 2s;
}
div:nth-of-type(1) {
animation-fill-mode: none;
}
div:nth-of-type(2) {
animation-fill-mode: forwards;
}
div:nth-of-type(3) {
animation-fill-mode: backwards;
}
div:nth-of-type(4) {
animation-fill-mode: both;
}
@keyframes myAnimation {
0% { left: 0px; background: yellow; }
100% { left: 200px; background: blue; }
}
</style>
</head>
<body>
<h1>animation-fill-mode</h1>
<div>none</div>
<p>대기 : 시작 프레임(from)에 설정한 스타일을 적용하지 않고 대기한다.</p>
<p>종료 : 애니메이션 실행 전 상태로 애니메이션 요소의 프로퍼티값을 되돌리고 종료한다.</p>
<div>forwards</div>
<p>대기 : 시작 프레임(from)에 설정한 스타일을 적용하지 않고 대기한다.
<p>종료 : 종료 프레임(to)에 설정한 스타일을 적용하고 종료한다.
<div>backwards</div>
<p>대기 : 시작 프레임(from)에 설정한 스타일을 적용하고 대기한다.
<p>종료 : 애니메이션 실행 전 상태로 애니메이션 요소의 프로퍼티값을 되돌리고 종료한다.
<div>both</div>
<p>대기 : 시작 프레임(from)에 설정한 스타일을 적용하고 대기한다.
<p>종료 : 종료 프레임(to)에 설정한 스타일을 적용하고 종료한다.
</body>
</html>
애니메이션 재생 상태(재생 또는 중지)를 지정한다. 기본값은
running
이다.
<!DOCTYPE html>
<html>
<head>
<style>
div {
width: 100px;
height: 100px;
background: red;
position: relative;
/*name duration timing-function delay iteration-count direction fill-mode play-state*/
animation: move 5s infinite;
}
div:hover {
background: blue;
animation-play-state: paused;
}
div:active {
background: yellow;
animation-play-state: running;
}
@keyframes move {
from { left: 0px; }
to { left: 200px; }
}
</style>
</head>
<body>
<h1>animation-play-state</h1>
<div></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style>
.box {
position: relative;
width: 100px;
height: 100px;
background-color: red;
animation-name: move;
animation-duration: 5s;
animation-play-state: paused; /* 초기 애니메이션 재생 상태: 정지 */
animation-iteration-count: infinite;
}
/* @keyframes rule */
@keyframes move {
from {
left: 0;
}
to {
left: 300px;
}
}
</style>
</head>
<body>
<div class="box"></div>
<button class="start">start animation</button>
<button class="pause">pause animation</button>
<script>
const box = document.querySelector('.box');
document.querySelector('.start').addEventListener('click', function () {
// trigger animation
// prefixes would be needed...
box.style.animationPlayState = 'running';
});
document.querySelector('.pause').addEventListener('click', function () {
// pause animation
// prefixes would be needed...
box.style.animationPlayState = 'paused';
});
</script>
</body>
</html>
모든 애니메이션 프로퍼티를 한번에 지정한다. 값을 지정하지 않은 프로퍼티에는 기본값이 지정된다.
animation-duration은 반드시 지정해야 한다. 지정하지 않는 경우 기본값 0s가 셋팅되어 어떠한 애니메이션도 실행되지 않는다.
animation: name duration timing-function delay iteration-count direction fill-mode play-state
//기본 값
animation: none 0 ease 0 1 normal none running
트랜스폼(Transform)은 요소에
이동(translate)
회전(rotate)
확대축소(scale)
비틀기(skew)
효과를 부여하기 위한 함수를 제공한다. 단 애니메이션 효과를 제공하지는 않기 때문에 정의된 프로퍼티가 바로 적용되어 화면에 표시된다.
트랜스폼은 애니메이션 효과를 위해 사용하여야 하는 것은 아니지만 애니메이션 효과를 부여할 필요가 있다면 트랜지션이나 애니메이션과 함께 사용한다.
2D 트랜스폼은 프로퍼티값으로 변환함수(transform function)를 사용한다.
transform function | 설명 | 단위 |
---|---|---|
translate(x,y) | 요소의 위치를 X축으로 x만큼, Y축으로 y만큼 이동시킨다. | px, %, em 등 |
translateX(n) | 요소의 위치를 X축으로 x만큼 이동시킨다. | px, %, em 등 |
translateY(n) | 요소의 위치를 Y축으로 y만큼 이동시킨다. | px, %, em 등 |
scale(x,y) | 요소의 크기를 X축으로 x배, Y축으로 y배 확대 또는 축소 시킨다. | 0과 양수 |
scaleX(n) | 요소의 크기를 X축으로 x배 확대 또는 축소 시킨다. | 0과 양수 |
scaleY(n) | 요소의 크기를 Y축으로 y배 확대 또는 축소 시킨다. | 0과 양수 |
skew(x-angle,y-angle) | 요소를 X축으로 x 각도만큼, Y축으로 y 각도만큼 기울인다. | +/- 각도(deg) |
skewX(x-angle) | 요소를 X축으로 x 각도만큼 기울인다. | +/- 각도(deg) |
skewY(y-angle) | 요소를 Y축으로 y 각도만큼 기울인다. | +/- 각도(deg) |
rotate(angle) | 요소를 angle만큼 회전시킨다. | /- 각도(deg) |
변환함수를 프로퍼티값으로 쉼표없이 나열한다. 나열순서에 따라 차례대로 효과가 적용된다.
transform: func1 func2 func3 ...;
<!DOCTYPE html>
<html>
<head>
<style>
.box {
width: 95px;
height: 95px;
line-height: 95px;
color: white;
text-align: center;
border-radius: 6px;
}
.original {
margin: 30px;
border: 1px dashed #cecfd5;
background: #eaeaed;
float: left;
}
.child {
background: #2db34a;
cursor: pointer;
}
.translate {
transform: translate(10px, 50px);
}
.scale {
transform: scale(.75);
}
.skew {
transform: skew(5deg, -20deg);
}
.rotate {
transform: rotate(70deg);
}
.complex {
transform: scale(.5) rotate(20deg);
}
/* Animation Effect */
.translate:hover {
transition: transform 1s linear;
transform: translate(0px, 0px);
}
/* .translate:hover {
animation: translate 1s linear forwards;
}
@keyframes translate {
100% {
transform: translate(0px, 0px);
}
} */
.scale:hover {
transition: transform 1s linear;
transform: scale(1);
}
.skew:hover {
transition: transform 1s linear;
transform: skew(0, 0);
}
.rotate:hover {
transition: transform 1s linear;
transform: rotate(0);
}
.complex:hover {
transition: transform 1s linear;
transform: scale(1) rotate(0);
}
</style>
</head>
<body>
<div class="original box">
<div class="child box translate">translate</div>
</div>
<div class="original box">
<div class="child box scale">scale</div>
</div>
<div class="original box">
<div class="child box skew">skew</div>
</div>
<div class="original box">
<div class="child box rotate">rotate</div>
</div>
<div class="original box">
<div class="child box complex">complex</div>
</div>
</body>
</html>
요소의 기본기준점을 설정할 때 사용된다. 기본기준점은 요소의 정중앙이다.(50%,50%)
%
px
top
left
bottom
right
을 사용할 수 있다.0, 0
은 top left
, 100% 100%
는 bottom right
과 같은 값이다.<!DOCTYPE html>
<html>
<head>
<style>
.box {
width: 150px;
height: 150px;
line-height: 150px;
color: white;
text-align: center;
border-radius: 6px;
}
.original {
margin: 20px;
border: 1px dashed #cecfd5;
background: #eaeaed;
float: left;
}
.child {
background: #2db34a;
cursor: pointer;
}
.scale1:hover {
transition: transform 1s linear;
transform-origin: 0 0;
transform: scale(.5);
}
.scale2:hover {
transition: transform 1s linear;
transform-origin: 50% 50%;
transform: scale(.5);
}
.scale3:hover {
transition: transform 1s linear;
transform-origin: 100% 100%;
transform: scale(.5);
}
.translate:hover {
transition: transform 1s linear;
/*transform-origin: 100% 100%;*/
transform: translate(10px, 10px);
}
</style>
</head>
<body>
<div class="original box">
<div class="child box scale1">scale1</div>
</div>
<div class="original box">
<div class="child box scale2">scale2</div>
</div>
<div class="original box">
<div class="child box scale3">scale3</div>
</div>
<div class="original box">
<div class="child box translate">translate</div>
</div>
</body>
</html>
3D 트랜스폼은 프로퍼티값으로 변환함수(transform function)를 사용한다. 사용할 수 있는 변환함수는 다음과 같다.
transform function | 설명 | |
---|---|---|
translate3d(x,y,z) | 요소의 위치를 X축으로 x만큼, Y축으로 y만큼 Z축으로 z만큼 이동시킨다. | px, %, em 등 |
translateX(n) | 요소의 위치를 X축으로 x만큼 이동시킨다. | px, %, em 등 |
translateY(n) | 요소의 위치를 Y축으로 y만큼 이동시킨다. | px, %, em 등 |
translateZ(n) | 요소의 위치를 Z축으로 z만큼 이동시킨다. | px, %, em 등 |
scale3d(x,y) | 요소의 크기를 X축으로 x배, Y축으로 y배, Z축으로 z배 확대 또는 축소 시킨다. | 0과 양수 |
scaleX(n) | 요소의 크기를 X축으로 x배 확대 또는 축소 시킨다. | 0과 양수 |
scaleY(n) | 요소의 크기를 Y축으로 y배 확대 또는 축소 시킨다. | 0과 양수 |
scaleZ(n) | 요소의 크기를 Z축으로 z배 확대 또는 축소 시킨다. | 0과 양수 |
rotate3d(x,y,z) | 요소를 X축으로 x각도, Y축으로 y각도, Z축으로 z각도 회전시킨다. | +/- 각도(deg) |
rotateX(x) | 요소를 X축으로 x각도 회전시킨다. | +/- 각도(deg) |
rotateY(y) | 요소를 Y축으로 y각도 회전시킨다. | +/- 각도(deg) |
rotateZ(z) | 요소를 Z축으로 z각도 회전시킨다. | +/- 각도(deg) |
웹디자인 관점에서 폰트의 선택
은 중요한 의미를 갖는다. 대부분의 정보는 텍스트와 이미지로 전달되고 아직은 텍스트가 주
를 이루기 때문에 더욱 그러하다. 이전에는 웹에서 사용할 수 있는 아름다운 한글 폰트가 적어 포토샵 등으로 로컬 폰트를 사용하여 텍스트를 이미지로 만들어 사용하였다. 이것은 많은 트래픽을 유발
하고 웹크롤러가 정보를 수집할 수 없어
SEO관점에서도 바람직하지 않다.
웹페이지는 불특정 사용자
를 위해 제작되기 때문에 어떤 디바이스
의 어떤 OS
를 사용하는 사용자가 웹페이지에 접근할 지 알 수 없다. 웹페이지를 구성하는 HTML
CSS
JavaScript
파일이 사용자의 요청에 의해 서버에서 클라이언트로 다운로드되어 실행되는 것과 같이 폰트 또한 서버에서 클라이언트로 다운로드되어 실행
될 수 있다면 이 문제는 해결될 수 있다.
이러한 문제를 해결할 수 있는 방법이 바로 웹폰트이다. 웹폰트는 사용자가 웹페이지를 요청한 순간
CSS에 기술된 필요 폰트가 서버에서 클라이언트로 전송
된다. 좀 더 구체적으로 말하면 매번 다운로드되는 것은 아니고 클라이언트에 해당 폰트가 존재하지 않을 경우 전송된다.
웹폰트를 사용하는 방법 중 가장 간단한 방법은 CDN 링크
를 사용하는 것이다. 아래는 구글에서 제공하는 웹폰트를 사용하는 방법이다.
@import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css);
* { font-family: 'Nanum Gothic', sans-serif; }
@import rule의 url 함수는 서버에서 혹은 지정된 url에서 파일을 찾아 다운로드한다.
Google Font를 사용하기 위해 CDN 링크
를 사용하는 방법은 간편하고 서버 폰트 로딩 방식
보다는 빠른 방법이지만 로컬 폰트를 사용하는 것
에 비해 로딩 속도가 느릴 수 있다.
여러 개의 폰트를 사용한다면 로딩에 더욱 시간이 걸릴 것이다. 또한 CDN 링크를 제공하지 않는 폰트는 사용할 방법이 없다. 이러한 단점을 보완한 방법이 서버 폰트 로딩 방식
이다.
@font-face 규칙
으로 폰트를 등록하고font-family
프로퍼티로 폰트를 선택하여 사용할 수 있다.
/* IE 9~ & all browsers */
@font-face {
font-family: myFontName;
src: url("myFont.woff");
}
* { font-family: myFontName, sans-serif; }
일반적으로 사용되는 검증된 웹폰트 사용 방법이다. 브라우저에 따라 필요한 폰트만을 다운로드할 수 있다.
@font-face {
font-family:"Nanum Gothic";
src:url("NanumGothic.eot"); /* IE 9 호환성 보기 모드 대응 */
src:local("☺"), /* local font 사용 방지. 생략 가능 */
url("NanumGothic.eot?#iefix") format('embedded-opentype'), /* IE 6~8 */
url("NanumGothic.woff") format('woff'); /* 표준 브라우저 */
}
* { font-family: "Nanum Gothic", sans-serif; }
영문과 한글을 혼용하는 경우 먼저 영문 폰트, 그 다음 한글 폰트를 지정하여야 한다. 한글 폰트부터 지정하면 영문에도 한글 폰트가 지정된다.
font-family: 'Lora', 'KoPub Batang', 'Times New Roman', serif;
웹 페이지는 style
과 layout
을 담당하는 CSS를 사용하여 layout을 구성하는 것이 바람직하다.
블록 레벨 요소들을 원하는 위치에 배열 레이아웃
화면의 크기에 따라 적절히 화면 구성을 변화시키는 반응형 웹 디자인(Responsive Web Design)
CSS를 사용하여 layout을 구성할 때에 자주 사용되는 핵심 기술은 float
이다. layout이란 웹사이트를 구성하는 요소들을 배치할 공간을 분할하고 정렬
하는 것이다. 공간을 분할할 때는 먼저 행을 구분한 후, 행 내부 요소를 분리하는 것이 일반적이다.
대부분의 웹사이트는
Navigation Bar
를 가지고 있다. Navigation Bar는 웹사이트의 필수 구성 요소라고 할 수 있을 것이다.
1-1. Navigation Bar는 기본적으로
링크들의 리스트
이다. 따라서ul
li
tag를 이용하여 작성하는 것이 일반적이다.
<!DOCTYPE html>
<html>
<head>
<style>
/* Simple Reset CSS */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #58666e;
background-color: #f0f3f4;
}
li {
list-style: none;
}
a {
text-decoration: none;
}
</style>
</head>
<body>
<div id="wrap">
<header>
<a class="logo" href="#home">
<img src="https://poiemaweb.com/img/logo.png" height="36px">
</a>
<nav>
<ul class="nav-items">
<li><a href="#home">Home</a></li>
<li><a href="#news">News</a></li>
<li><a href="#contact">Contact</a></li>
<li><a href="#about">About</a></li>
</ul>
</nav>
</header>
</div>
</body>
</html>
1-2. header 요소에 화면폭 만큼의 width와 고정 height를 지정한다.
background-color
와box-shadow
효과를 추가한다.
header {
width: 100%;
height: 60px;
z-index: 2000;
background-color: #fff;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05);
}
1-3. float 프로퍼티를 이용하여 Navigation bar를 우측정렬한다.
nav {
float: right;
}
1-4. 아래의 logo image를 수직으로 중앙 정렬한다.
<a class="logo" href="#home"><img src="https://poiemaweb.com/img/logo.png" height="36px"></a>
logo image를 포함하는 a tag(.logo)의 height
를 logo image와 같은 height인 36px
로 지정하고, 상하 margin
을 12px
씩 부여하면 logo 요소의 높이는 60px
이 되고 header의 height와 같아져 이미지는 수직 중앙 정렬
된다.
1-5. a tag는 inline 요소이므로 margin을 정의하기 위해서
display: inline-block;
을 설정한다.
img tag에 부여한 height 어트리뷰트를 css로 옮긴다.
.logo {
display: inline-block;
height: 36px;
margin: 12px 0 12px 25px;
}
.logo > img { height: 36px; }
1-6. 수직 정렬되어 있는 Navigation bar를 수평 정렬한다.
block 요소인 li에display: inline-block;
를 설정하여 inline 요소와 같이 가로로 정렬케 한다.
.nav-items > li {
display: inline-block;
}
1-7. 수평 정렬된 Navigation bar 수직 중앙 정렬한다.
line-height: 60px;
으로 텍스트의 높이를 header의 height와 동일하게 60px로 고정시킨다.
그리고 텍스트 간 적당한 간격 유지를 위해 padding을 정의한다.
.nav-items > li > a {
line-height: 60px;
padding: 0 30px;
color: rgba(0, 0, 0, 0.4);
}
1-8. 마우스가 Navigation bar 위에 올라오면 Navigation item의 텍스트 색상이 변경되도록 한다.
.nav-items > li > a:hover {
color: rgba(0, 0, 0, 0.8);
}
1-9. 완성된 Navigation bar의 코드
<!DOCTYPE html>
<html>
<head>
<style>
/* Simple Reset CSS */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #58666e;
background-color: #f0f3f4;
}
li {
list-style: none;
}
a {
text-decoration: none;
}
header {
width: 100%;
height: 60px;
z-index: 2000;
background-color: #fff;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05);
}
nav {
float: right;
}
.logo {
display: inline-block;
height: 36px;
margin: 12px 0 12px 25px;
}
.logo > img { height: 36px; }
.nav-items > li {
display: inline-block;
}
.nav-items > li > a {
line-height: 60px;
padding: 0 30px;
color: rgba(0,0,0,0.4);
}
.nav-items > li > a:hover {
color: rgba(0,0,0,0.8);
}
</style>
</head>
<body>
<div id="wrap">
<header>
<a class="logo" href="#home">
<img src="https://poiemaweb.com/img/logo.png">
</a>
<nav>
<ul class="nav-items">
<li><a href="#home">Home</a></li>
<li><a href="#news">News</a></li>
<li><a href="#contact">Contact</a></li>
<li><a href="#about">About</a></li>
</ul>
</nav>
</header>
</div>
</body>
</html>
콘텐츠의 영역을
Section
, 콘텐츠에 대한 Navigation item이나 부가 정보 영역을Aside
라 한다.
2-1.
Section
영역은 다시article
영역으로 구분할 수 있다. 이 두개의 영역은float
프로퍼티를 사용하여 수평 정렬하는 것이 일반적이다.header
요소 뒤에aside
section
article
을 포함하는content-wrap
요소를 정의한다.
<div id="content-wrap">
<aside>
<h1>Aside</h1>
<ul>
<li><a href="#" class="active">London</a></li>
<li><a href="#">Paris</a></li>
<li><a href="#">Tokyo</a></li>
<li><a href="#">Newyork</a></li>
</ul>
</aside>
<section>
<article id="london">
<h1>London</h1>
<p>...</p>
</article>
<article id="paris">
<h1>Paris</h1>
<p>...</p>
</article>
<article id="tokyo">
<h1>Tokyo</h1>
<p>...</p>
</article>
<article id="newyork">
<h1>Newyork</h1>
<p>...</p>
</article>
</section>
<!-- end of content-wrap -->
</div>
2-2.
aside
를 좌측정렬,section
을 우측 정렬한다. 이때float
프로퍼티가 선언된 두개의 자식 요소를 포함하는 부모 요소의 높이가 정상적인 값을 가지지 못하는 문제를 해결해야 한다.
/* clearfix */
#content-wrap:after {
content: "";
display: block;
clear: both;
}
aside {
float: left;
width: 20%;
}
section {
float: right;
width: 80%;
}
2개의 블록 영역이 수평 정렬되었고 wrap 요소도 정상적인 높이를 가지게 되었다. 그런데 아래 그림처럼 화면을 아래로 스크롤하면 header 영역도 따라 올라가 버려 navigation bar가 사라져 버리는 현상이 발생한다. navigation bar가 화면에 없으면 조작이 불편할 수 있으므로 navigation bar를 화면 상단에 고정
시켜야 한다.
2-3.
fixed
프로퍼티를 사용하여 header 요소를 상단에 고정시킨다. 스크롤이 되더라도 화면에서 사라지지 않고 항상 같은 곳에 위치한다.
header {
/* for sticky header */
position: fixed;
top: 0;
...
}
2-4. contents 영역 상단이 header 영역과 겹치므로 header의 height 만큼 아래로 끌어 내린다.
#wrap {
/* margin-top = header height */
margin-top: 60p;
}
header 영역은 고정되었다. 그런데 화면이 스크롤될 때 좌측 aside의 navigation이 사라지는 것은 마찬가지로 불편할 수 있다.
2-5. aside에
float: left;
를 삭제하고 header와 같이position: fixed;
를 추가한다.%
로 지정했던width
도 고정폭으로 변경한다.section
영역의%
width
도 삭제하여aside
영역 만큼 우측으로 밀어서 나머지 영역을 모두 차지하도록 한다.
aside {
/* for fixed side bar */
position: fixed;
top: 60px;
bottom: 0;
width: 200px;
}
section {
float: right;
margin-left: 200px;
}
2-6. aside navigation의 style을 정리한다. 현재 active한 item을 컬러로 구분할 수 있게 하고 마우스 hover상태일 때도 컬러로 구분할 수 있게 한다. 또한 텍스트의 style도 정리한다.
aside {
/* for fixed side bar */
position: fixed;
top: 60px;
bottom: 0;
width: 200px;
padding-top: 25px;
background-color: #333;
}
/* aside navigation */
aside > ul {
width: 200px;
}
aside > ul > li > a {
display: block;
color: #fff;
padding: 10px 0 10px 20px;
}
aside > ul > li > a.active {
background-color: #4CAF50;
}
aside > ul > li > a:hover:not(.active) {
background-color: #555;
}
aside > h1 {
padding: 20px 0 20px 20px;
color: #fff;
}
/* Section */
section {
float: right;
/* aside width */
margin-left: 200px;
}
article {
margin: 10px;
padding: 25px;
background-color: white;
}
heading tag(h1)의 크기가 위치한 영역에 따라 다름에 주의하여야 한다. 즉, header내의 h1은 section내의 h1 보다 크다. 이것을 방지하기 위해서는 다음을 Reset CSS에 추가할 필요가 있다. 크기는 적당히 조절하면 된다. 다른 텍스트 태그의 style도 정리한다.
h1 { font-size: 1.8em; }
h1, h2, h3, h4, h5, h6, p {
margin: 10px 5px;
}
content-wrap 영역 다음에 footer를 배치한다.
<footer>© Copyright 2016 ungmo2</footer>
footer도 고정되어 있을 필요가 있지만 본문을 가리는 것
은 곤란하다. 따라서 fixed 프로퍼티를 설정해서는 않된다. fixed 프로퍼티는 스크롤이 되어도 언제나 그자리를 고수하기 때문이다. footer는 absolute
프로퍼티를 설정한다. absolute
를 사용하면 다른 요소가 먼저 위치를 점유하고 있어도 뒤로 밀리지 않고 덮어쓰게 된다.
footer {
/* footer를 aside위에 올리기 위해 사용(부유객체) */
position: absolute;
height: 60px;
width: 100%;
padding: 0 25px;
line-height: 60px;
color: #8a8c8f;
border-top: 1px solid #dee5e7;
background-color: #f2f2f2;
}
이처럼 레이아웃을 구분하고 스타일을 적용하여 간단한 웹의 구성을 제작 할 수 있다.
사용자가 어떤 디바이스
로 웹사이트를 방문할 지 알 수 없다. layout
은 방문자의 화면 해상도를 고려
하여야 한다. 가로폭이 너무 큰 layout을 작성하면 작은 해상도 모니터로 방문하였을 때 가로 스크롤이 생겨서 사용이 불편할 수도 있다. 또한 스마트폰이나 태블릿 등 모바일 기기는 화면이 작기 때문에 가독성에 더욱 신경써야 한다.
보통 웹사이트가 축소되어 가로 스크롤 없이 콘텐츠를 볼 수 있으나 글자가 너무 작아지기 때문이다. 데스크탑용
테블릿용
모바일용
웹사이트를 별도 구축할 수도 있지만 One Source Multi Use의 관점에서 올바른 해결책은 아니다. 이러한 문제를 해결하는 방법 중의 하나가 반응형 웹디자인(Responsive Web Design)
이다. 화면 해상도
에 따라 가로폭
이나 배치
를 변경하여 가독성을 높이는 것
이다.
즉, 하나의 웹사이트를 구축하여 다양한 디바이스의 화면 해상도에 최적화된 웹사이트를 제공하는 것이다.
viewport란 웹페이지의 가시영역을 의미한다. viewport는 디바이스에 따라 차이가 있다.
예를 들어 모바일 브라우저는 주화면이 세로 화면
이고 윈도우 resize가 불가
하며 화면 터치를 사용
하는 등 데스크탑 브라우저와 구성이나 형태가 다르다.또한 모바일의 화면은 데스크탑 화면보다 훨씬 작으므로 데스크탑용 웹페이지를 그대로 모바일에 출력하면 가독성이 현저히 나빠진다. 따라서 viewport
를 이용하여 디바이스의 특성과 디바이스의 화면 크기 등을 고려하여 각종 디바이스 사용자에게 최적화된 웹페이지를 제공할 수 있다.
프로퍼티 | Description | 사용예 |
---|---|---|
width | viewport 너비(px). 기본값: 980px | width=240 |
width=device-width | ||
height | viewport 높이(px) | height=800 |
width=device-height | ||
initial-scale | viewport초기 배율 | initial-scale=1.0 |
user-scale | 확대 축소 가능 여부 | user-scale=no |
maximum-scale | viewport 최대 배율 | maximum-scale=2.0 |
minimum-scale | viewport 최소 배율 | minimum-scale=1.0 |
meta tag
에서는 px
단위 를 사용하며 단위 표현은 생략한다. 복수개의 프로퍼티를 사용할 때는 쉼표(,)
로 구분한다. 일반적으로 viewport meta tag는 모바일 디바이스에서만 적용된다.
<meta name="viewport" content="width=device-width, initial-scale=1.0">
가장 일반적인 viewport 설정이다. 가로폭을 디바이스의 가로폭에 맞추고 초기 화면 배율을 100%로 설정하는 것을 의미한다.
@media는 서로 다른 미디어 타입(print, screen…)에 따라 각각의 styles을 지정하는 것을 가능하게 한다.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
@media screen {
* { color: red; }
}
@media print {
* { color: blue; }
}
</style>
</head>
<body>
<h1>@media practice</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</body>
</html>
반응형 웹디자인에 사용되는 핵심 기술은 @media
이다.@media
을 사용하여 미디어 별로 style을 지정하는 것을 Media Query
라 한다. 디바이스를 지정하는 것뿐만 아니라 디바이스의 크기나 비율까지 구분할 수 있다.
@media not|only mediatype and (expressions) {
CSS-Code;
}
@media screen and (min-width: 480px) {
body {
background-color: lightgreen;
}
}
프로퍼티 | Description |
---|---|
width | viewport 너비(px) |
height | viewport 높이(px) |
device-width | 디바이스의 물리적 너비(px) |
device-height | 디바이스의 물리적 높이(px) |
orientation | 디바이스 방향 (가로 방향: landscape, 세로방향: portrait) |
device-aspect-ratio | 디바이스의 물리적 width/height 비율 |
color | 디바이스에서 표현 가능한 최대 색상 비트수 |
monochrome | 흑백 디바이스의 픽셀 당 비트수 |
resolution | 디바이스 해상도 |
orientation
을 제외한 모든 프로퍼티는 min
/ max
접두사를 사용할 수 있다. 일반적으로 반응형 웹 디자인은 viewport
너비(width 프로퍼티)를 기준으로 한다. viewport의 width 프로퍼티를 이용하여 viewport 너비에 따라 반응하는 범위(breakpoint)
를 지정할 수 있다.
반응형 웹 해상도 분기점 (2022년)
1) 최소 반응형 레이아웃과 코드
/* 데스크탑 */
@media screen and (max-width:1023px) {
/* 타블렛 */
}
@media screen and (max-width:767px) {
/* 모바일 */
}
2) 가로모드 디바이스 지원 반응형 레이아웃과 코드
/* 빅데스크탑 */
@media screen and (max-width:1799px) {
/* 데스크탑 */
}
@media screen and (max-width:1199px) {
/* 타블렛 가로 */
}
@media screen and (max-width:899px) {
/* 모바일 가로, 타블렛 세로 */
}
@media screen and (max-width:599px) {
/* 모바일 세로 */
}
3) 부트스트랩 반응형 레이아웃과 코드
크기 | 키워드 | 기준점 해상도 | 디바이스 |
---|---|---|---|
아주 작은(Extra small) | xs | 576px 미만 | 스마트폰 세로 |
작은(Small) | sm | 576px 이상 | 스마트폰 가로 |
중간(Medium) | md | 768px 이상 | 타블렛 |
큰(Large) | lg | 992px 이상 | 데스크탑 |
아주 큰(Extra large) | xl | 1200px 이상 | 큰 데스크탑 |
/* 큰 데스크탑 */
@media screen and (max-width:575.98px) {
/* 스마트폰 세로 */
}
@media screen and (max-width:767.98px) {
/* 스마트폰 가로 */
}
@media screen and (max-width:991.98px) {
/* 타블렛 */
}
@media screen and (max-width:1199.98px) {
/* 데스크탑 */
}
레이아웃의 구조를 위해 제작한 웹을 반응형 웹으로 수정 할 수 있다.
3-1.
디바이스 해상도
에 따라 반응할 수 있도록viewport meta tag
와media query
를 추가한다.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* Media Query */
/* for Desktop: 801px ~ */
/* for tablet: ~ 800px */
@media screen and (max-width: 800px) {
}
/* for smartphone: ~ 480px */
@media screen and (max-width: 480px) {
}
</style>
</head>
스마트폰
태블릿
데스크탑
그룹의 3단계로 구분하여 breakpoint
를 정의하였다. Non Mobile First Method로 정의하였기 때문에 Media Query로 정의하지 않은 스타일은 데스크탑 그룹을 위한 코드가 된다.
/* for Desktop: 801px ~ */
/* for tablet: ~ 800px */
@media screen and (max-width: 800px) {
}
최대 viewport width를 800px로 한정하였다는 것은 화면 크기가 800px 이하인 디바이스(태블릿)를 위한 정의란 의미가 된다. 화면 크기가 800px 이하인 디바이스에서 웹사이트가 표시될 때 실행된다.
/* for smartphone: ~ 480px */
@media screen and (max-width: 480px) {
}
최대 viewport width를 480px로 한정하였다는 것은 화면 크기가 480px 이하인 디바이스(스마트폰)를 위한 정의란 의미가 된다. 위 예제 내에 정의 되는 스타일은 화면 크기가 480px 이하인 디바이스에서 웹사이트가 표시될 때 실행된다. CSS 적용 우선 순위 (Cascading Order)
에 따라 나중에 선언된 스타일이 우선 적용된다. 따라서 Media Query는 기술 순서에 의미가 있다. 만일 스마트폰용 스타일을 태블릿용 스타일보다 먼저 기술하면 최종적으로 태블릿용 스타일이 적용된다. 따라서 Non Mobile First 방식의 경우, max-width의 값이 큰 것부터 기술하여 한다.
/* Media Query */
/* for Desktop: 801px ~ */
/* for smartphone: ~ 480px */
/*
Media Query는 기술 순서에 의미가 있다.
만일 스마트폰용 스타일을 태블릿용 스타일보다 먼저 기술하면 최종적으로 태블릿용 스타일이 적용된다.
Non Mobile First Method의 경우, max-width의 값이 큰 것부터 기술하여 한다.
*/
@media screen and (max-width: 480px) {
}
/* for tablet: ~ 800px */
@media screen and (max-width: 800px) {
}
일반적으로
Mobile-first
방식은 해상도가 작은 순서로,Non Mobile-first
방식은 해상도가 큰 순서로 기술한다.
3-2. 데스크탑 layout에서 화면이 작아질 때 header navigation bar가 header 영역 아래로 내려오는 현상이 발생하였다. 이를 보완하기 위해 다음과 같이 태블릿에서의 layout을 정의한다.
viewport width
가 800px 이하가 되면 header 영역을 2단(logo영역과 navigation bar영역)으로 구분하기 위하여
header 영역의 높이를 현재(60px)의 2배
로 넓힌다. 그리고 logo image과 navigation bar를 centering
한다.
@media screen and (max-width: 800px) {
header {
height: 120px;
text-align: center;
}
}
이때 aside, section영역도 header의 height
만큼 내려가야 한다.
@media screen and (max-width: 800px) {
header {
height: 120px;
text-align: center;
}
#wrap {
/* margin-top = header height */
margin-top: 120px;
}
aside {
top: 120px;
}
}
3-3. 가로로 정렬되어 있던 logo image과 navigation bar를 상단과 하단으로 분리 배치하기 위하여 navigation bar의
float: right;
프로퍼티를 해제한다. 그러면 navigation bar는block
프로퍼티를 가지게 되어 logo image의 아래 영역으로 내려가게 된다.
@media screen and (max-width: 800px) {
header {
height: 120px;
text-align: center;
}
nav {
float: none;
/*margin-right: 0;*/
}
#wrap {
/* margin-top = header height */
margin-top: 120px;
}
aside {
top: 120px;
}
}
태블릿 layout에서는 header 영역을 2단으로 분리하여 navigation bar는 header 하단 영역에 배치하였다. 하지만 스마트폰의 viewport width
는 가로로 나란히 정렬되어 있는 navigation bar를 모두 담기에는 너무 좁다.
3-4. 다음과 같이 스마트폰 layout을 정의한다.
3-5. 우측 navigation icon을 클릭하면 navigation bar가 수직 정렬되어 화면에 나타나도록 한다. 한번 더 클릭하면 화면에서 사라지도록 한다. 이때 navigation icon에
animation
효과를 부여한다.
3-6. nav 요소 내에 클릭할 수 있는 navigation icon을 만들기 위한 html tag 를 추가한다.
label tag
의for
프로퍼티값과input tag
의id
프로퍼티값이 일치하여야 한다.
<nav>
<input class="nav-toggle" id="nav-toggle" type="checkbox">
<label class="navicon" for="nav-toggle"><span class="navicon-bar"></span></label>
<ul class="nav-items">
<li><a href="#home">Home</a></li>
<label for="remeber-pw">Remeber password?</label>
<input type="checkbox" name="remeber-pw" id="remeber-pw">
input checkbox 요소의 id 프로퍼티값과 label 요소의 for 프로퍼티값을 일치시켜 연동하면 label 요소를 클릭하여도 input checkbox 요소가 클릭된다.
이것을 이용하여 label 요소의 콘텐츠를 커스텀 navigation icon으로 만들어 주고 input checkbox 요소의 기본 외관을 비표시
하는 방법이다.
navigation icon은 input checkbox 요소와 연동되어야 하므로 label 요소
를 사용하였다. 즉, navigation icon을 클릭하면 checkbox input tag도 checked 상태가 된다.
3-7. navigation icon은 header 우측의 절대 위치에 배치되어야 하므로
position: absolute;
를 지정한다.
.navicon {
cursor: pointer;
height: 60px;
padding: 28px 15px;
position: absolute;
top: 0; right: 0;
}
absolute
프로퍼티는 부모 요소 또는 가장 가까이 있는 조상 요소(static 제외)를 기준으로 좌표 프로퍼티(top
bottom
left
right
)만큼 이동한다. 즉, relative
absolute
fixed
프로퍼티가 선언되어 있는 부모 또는 조상 요소를 기준으로 위치가 결정된다. navigation icon은 body를 기준으로 위치
하면 되므로 부모 요소에 별도의 처리가 필요없다.
3-8. label tag 내의 span tag의 style을 정의한다. span tag는 navigation icon의 내부 막대 3개(클릭 시에는 X 표시)를 표현하기 위해 정의했다.
.navicon-bar {
display: block;
width: 20px;
height: 3px;
background-color: #333;
}
3-9.
가상 요소 선택자 (Pseudo-Element Selector)
를 사용하여 navigation icon의 내부 막대 앞뒤 공간에 내부 막대를 추가한다.
.navicon-bar::before,
.navicon-bar::after {
background-color: #333;
content: "";
display: block;
height: 100%;
width: 100%;
position: absolute;
}
.navicon-bar::before {
top: -7px;
}
.navicon-bar::after {
top: 7px;
}
3-10. 절대 위치를 지정하기 위해
position: absolute;
를 사용하였으므로 가상 요소의 부모 요소인 span 요소(.navicon-bar)에position: relative;
를 추가한다.
.navicon-bar {
background-color: #333;
display: block;
position: relative;
width: 20px;
height: 3px;
}
아직 navigation icon을 클릭하여도 아무런 반응이 없다. navigation icon을 클릭하면 클릭되었음
을 사용자가 확인할 수 있도록 navigation icon의 style을 변화시킨다.
3-11. input checkbox tag의 가상 클래스 선택자
checked
를 이용하여 클릭되었을 때(input:checked)와 그렇지 않을 때를 구분할 수 있다. 중간에 위치한 막대를 없앤다. 그리고 상하 막대를 45도 회전시킨다. 이때 위치가 틀어지므로top: 0;
로 보정한다.
.nav-toggle:checked ~ .navicon > .navicon-bar {
background: transparent;
}
.nav-toggle:checked ~ .navicon > .navicon-bar::before {
transform: rotate(45deg);
top: 0;
}
.nav-toggle:checked ~ .navicon > .navicon-bar::after {
transform: rotate(-45deg);
top: 0;
}
3-12. navigation icon에
transition
효과를 부여하여 좀더 부드럽게 움직이도록 한다.
.navicon-bar {
background-color: #333;
display: block;
position: relative;
transition: background-color .2s ease-out;
width: 20px;
height: 3px;
}
.navicon-bar::before,
.navicon-bar::after {
background-color: #333;
content: "";
display: block;
height: 100%;
width: 100%;
position: absolute;
transition: all .2s ease-out;
}
navigation icon을 클릭하면 의도하지 않게 이미지가 선택되는 현상이 발생할 수 있다.
navigation icon이 텍스트
이기 때문에 발생하는 문제이다.텍스트 선택을 차단하는 방법인 user-select: none;
프로퍼티를 지정하여 회피할 수 있다.
.navicon {
cursor: pointer;
height: 60px;
padding: 28px 15px;
position: absolute;
top: 0; right: 0;
-webkit-user-select: none; /* Chrome all / Safari all */
-moz-user-select: none; /* Firefox all */
-ms-user-select: none; /* IE 10+ */
user-select: none; /* Likely future */
}
navigation icon과 checkbox input tag는 스마트폰 layout 이외의 경우, 화면에 표시되어서는 안된다. 따라서 display: none;
으로 화면에 표시되지 않도록 한다.
display: none;
은 해당 공간조차 점유하지 않지만visibility: hidden;
을 사용하면 해당 공간은 남아있고 표시만 되지 않는다.
CSS 적용 우선 순위 (Cascading Order)
를 고려하여 가장 마지막에 정의하는 것이 안전하다.
.nav-toggle {
display: none;
}
.navicon {
display: none;
}
3-13. tablet용 layout에서 header height를 2배로 하였으므로 mobile용 layout을 위해 다시 60px로 되돌린다.
@media screen and (max-width: 480px) {
header {
height: 60px;
}
}
스마트폰 layout에서는 navigation bar가 초기상태에서 비표시되어야 한다. 그리고 navigation icon은 표시되어야 한다. 아직 navigation icon을 완성하지 않았으므로 표시되지 않는다.
@media screen and (max-width: 480px) {
header {
height: 60px;
}
.nav-items {
display: none;
}
.navicon {
display: block;
}
}
3-14. 콘텐츠 영역이 아직 tablet layout에 맞추어 아래로 내려가 있다. header 영역 바로 아래로 다시 끌어 올린다.
@media screen and (max-width: 480px) {
/*...*/
#wrap {
/* margin-top = header height */
margin-top: 60px;
}
aside {
top: 60px;
}
/*...*/
}
3-15. 마지막으로 navigation icon을 클릭하면 navigation item이 표시되도록 한다.
@media screen and (max-width: 480px) {
...
.nav-toggle:checked ~ .nav-items {
display: block;
width: 100%;
background-color: #fff;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05);
}
.nav-items > li {
display: block;
}
.nav-items > li > a {
line-height: 50px;
}
}
Responsive Navigation Bar 완성
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
/* Simple Reset CSS */
* {
margin: 0; padding: 0;
box-sizing: border-box;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #58666e;
background-color: #f0f3f4;
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjus: 100%; /* iphone font size 변경 방지 */
}
li { list-style: none; }
a { text-decoration: none; }
h1, h2, h3, h4, h5, h6, p {
margin: 10px 5px;
}
h1 { font-size: 1.8em; }
#wrap {
width: 100%;
/* margin-top = header height */
margin-top: 60px;
}
/* Navigation bar */
header {
/* for sticky header */
position: fixed;
top: 0;
width: 100%;
height: 60px;
z-index: 2000;
background-color: #fff;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05);
}
.logo {
display: inline-block;
height: 36px;
margin: 12px 0 12px 25px;
}
.logo > img { height: 36px; }
nav {
float: right;
}
.nav-items {
margin-right: 20px;
}
.nav-items > li {
display: inline-block; /* 가로정렬 */
}
.nav-items > li > a {
line-height: 60px; /* for Vertical Centering */
padding: 0 30px; /* nav item간 간격 */
color: rgba(0,0,0,0.4);
}
.nav-items > li > a:hover {
color: rgba(0,0,0,0.8);
}
/* navigation icon for Mobile Layout */
.navicon {
cursor: pointer;
height: 60px;
padding: 28px 15px;
position: absolute;
top: 0; right: 0;
-webkit-user-select: none; /* Chrome all / Safari all */
-moz-user-select: none; /* Firefox all */
-ms-user-select: none; /* IE 10+ */
user-select: none; /* Likely future */
}
/* nav icon의 내부 막대 */
.navicon-bar {
background-color: #333;
display: block;
position: relative;
/* navigation icon animation */
transition: background-color .2s ease-out;
width: 20px;
height: 3px;
}
.navicon-bar::before,
.navicon-bar::after {
background-color: #333;
content: "";
display: block;
height: 100%;
width: 100%;
position: absolute;
/* navigation icon animation */
transition: all .2s ease-out;
}
.navicon-bar::before {
top: -7px;
}
.navicon-bar::after {
top: 7px;
}
/* toggle navigation icon */
.nav-toggle:checked ~ .navicon > .navicon-bar {
background: transparent;
}
.nav-toggle:checked ~ .navicon > .navicon-bar::before {
transform: rotate(45deg);
top: 0;
}
.nav-toggle:checked ~ .navicon > .navicon-bar::after {
transform: rotate(-45deg);
top: 0;
}
/* contents */
/* clearfix */
#content-wrap:after {
content: "";
display: block;
clear: both;
}
aside {
/* for fixed side bar */
position: fixed;
top: 60px;
bottom: 0;
width: 200px; /* 너비 고정 */
padding-top: 25px;
background-color: #333;
}
/* aside navigation */
aside > ul {
width: 200px;
}
aside > ul > li > a {
display: block;
color: #fff;
padding: 10px 0 10px 20px;
}
aside > ul > li > a.active {
background-color: #4CAF50;
}
aside > ul > li > a:hover:not(.active) {
background-color: #555;
}
aside > h1 {
padding: 20px 0 20px 20px;
color: #fff;
}
/* Section */
section {
float: right;
margin-left: 200px; /*aside width*/
}
article {
margin: 10px;
padding: 25px;
background-color: white;
}
/* footer */
footer {
/* footer를 aside위에 올리기 위해 사용(부유객체) */
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 60px;
padding: 0 25px;
line-height: 60px;
color: #8a8c8f;
border-top: 1px solid #dee5e7;
background-color: #f2f2f2;
}
.nav-toggle {
display: none;
}
.navicon {
display: none;
}
/* Media Query */
/* for tablet: ~ 800px */
@media screen and (max-width: 800px) {
header {
height: 120px;
text-align: center;
}
nav {
float: none;
margin-right: 0;
}
#wrap {
/* margin-top = header height */
margin-top: 120px;
}
aside {
top: 120px;
}
}
/* for smartphone: ~ 480px */
@media screen and (max-width: 480px) {
header {
height: 60px;
}
.nav-items {
display: none;
}
.navicon {
display: block;
}
#wrap {
/* margin-top = header height */
margin-top: 60px;
}
aside {
top: 60px;
}
/* View navigation item */
.nav-toggle:checked ~ .nav-items {
display: block;
width: 100%;
background-color: #fff;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05);
}
.nav-items > li {
display: block;
}
.nav-items > li > a {
line-height: 50px;
}
}
</style>
</head>
<body>
<div id="wrap">
<header>
<a class="logo" href="#home"><img src="https://poiemaweb.com/img/logo.png"></a>
<nav>
<input class="nav-toggle" id="nav-toggle" type="checkbox">
<label class="navicon" for="nav-toggle"><span class="navicon-bar"></span></label>
<ul class="nav-items">
<li><a href="#home">Home</a></li>
<li><a href="#news">News</a></li>
<li><a href="#contact">Contact</a></li>
<li><a href="#about">About</a></li>
</ul>
</nav>
</header>
<div id="content-wrap">
<aside>
<h1>Aside</h1>
<ul>
<li><a href="#" class="active">London</a></li>
<li><a href="#">Paris</a></li>
<li><a href="#">Tokyo</a></li>
<li><a href="#">Newyork</a></li>
</ul>
</aside>
<section>
<article id="london">
<h1>London</h1>
<p>London is the capital city of England. It is the most populous city in the United Kingdom, with a metropolitan area of over 13 million inhabitants.</p>
<p>Standing on the River Thames, London has been a major settlement for two millennia,its history going back to its founding by the Romans, who named it Londinium.</p>
<p>London, also referred to as Greater London, is one of 9 regions of England and the top-level subdivision covering most of the city's metropolis. The small ancient City of London at its core once comprised the whole settlement, but as its urban area grew, the Corporation of London resisted attempts to amalgamate the city with its suburbs, causing "London" to be defined in a number ways for different purposes.</p>
</article>
<article id="paris">
<h1>Paris</h1>
<p>London is the capital city of England. It is the most populous city in the United Kingdom, with a metropolitan area of over 13 million inhabitants.</p>
<p>Standing on the River Thames, London has been a major settlement for two millennia,its history going back to its founding by the Romans, who named it Londinium.</p>
<p>London, also referred to as Greater London, is one of 9 regions of England and the top-level subdivision covering most of the city's metropolis. The small ancient City of London at its core once comprised the whole settlement, but as its urban area grew, the Corporation of London resisted attempts to amalgamate the city with its suburbs, causing "London" to be defined in a number ways for different purposes.</p>
</article>
<article id="tokyo">
<h1>Tokyo</h1>
<p>London is the capital city of England. It is the most populous city in the United Kingdom, with a metropolitan area of over 13 million inhabitants.</p>
<p>Standing on the River Thames, London has been a major settlement for two millennia,its history going back to its founding by the Romans, who named it Londinium.</p>
<p>London, also referred to as Greater London, is one of 9 regions of England and the top-level subdivision covering most of the city's metropolis. The small ancient City of London at its core once comprised the whole settlement, but as its urban area grew, the Corporation of London resisted attempts to amalgamate the city with its suburbs, causing "London" to be defined in a number ways for different purposes.</p>
</article>
<article id="newyork">
<h1>Newyork</h1>
<p>London is the capital city of England. It is the most populous city in the United Kingdom, with a metropolitan area of over 13 million inhabitants.</p>
<p>Standing on the River Thames, London has been a major settlement for two millennia,its history going back to its founding by the Romans, who named it Londinium.</p>
<p>London, also referred to as Greater London, is one of 9 regions of England and the top-level subdivision covering most of the city's metropolis. The small ancient City of London at its core once comprised the whole settlement, but as its urban area grew, the Corporation of London resisted attempts to amalgamate the city with its suburbs, causing "London" to be defined in a number ways for different purposes.</p>
</article>
</section>
<!-- end of content-wrap -->
</div>
<footer>© Copyright 2016 ungmo2</footer>
<!-- end of wrap -->
</div>
</body>
</html>
현재 article은 layout에 상관없이 1행에 1개씩 배치되었다. responsive web design의 효과를 좀더 체감하기 위하여 1행에 2열로 배치한다.
4-1. article을 2열로 배치하기 위해서
width
값을 지정하여야 한다.%
로width
값을 지정하여 viewport에 상대적인 너비를 갖도록 한다.
4-2.
margin
도%
로 지정한다. 그리고float: left;
를 지정하여2열로 정렬
되도록 한다.
article {
width: 48.5%;
margin: 1%;
padding: 25px;
background-color: white;
float: left;
}
4-3. 짝수번째 배치되는 article의 좌측 마진과 3번째부터 등장하는 article의 위측 마진을 0로 하여 가운데 마진이 2배가 되는 것을 방지한다.
article:nth-of-type(2n) {
margin-left: 0;
}
article:nth-of-type(n+3) {
margin-top: 0;
}
4-4. tablet layout을 작성한다. 800px 이하로 화면이 작아지면 2열 배치되어 있던 article을 1열로 배치한다.
@media screen and (max-width: 800px) {
...
article {
width: inherit;
display: block;
margin: 10px;
float: none;
}
article:nth-of-type(2n) {
margin: 10px;
}
article:nth-of-type(n+2) {
margin-top: 0;
}
}
4-5. mobile layout을 작성한다. 480px 이하로 화면이 작아지면 고정 배치되어 있던 aside를 article 위로 올려 배치한다.
@media screen and (max-width: 480px) {
/*...*/
aside {
top: 60px;
position: static;
width: 100%;
padding: 5px 0;
}
/* aside navigation */
aside > ul {
width: 100%;
}
aside > h1 {
padding: 5px 0 10px 20px;
color: #fff;
}
section {
float: none;
margin-left: 0;
}
/*...*/
}
이렇게 PC기준의 레이아웃과 웹의 구조를 제작 해놓고 반응형 디자인으로 모바일용
태블릿용
PC용
웹을 디자인 할 수 있다.
Flexbox는 모던 웹을 위하여 제안된 기존 layout보다 더 세련된 방식의 니즈에 부합하기 위한 CSS3의 새로운 layout 방식이다. 요소의 사이즈가 불명확하거나 동적으로 변화할 때에도 유연한 레이아웃을 실현할 수 있다. 복잡한 레이아웃이라도 적은 코드로 보다 간단하게 표현할 수 있다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Flexbox Layout Example</title>
<style>
.flex-container {
margin: 10px;
padding: 15px;
border-radius: 5px;
background: #60B99A;
}
.flex-item {
margin: 10px;
padding: 20px;
color: #fff;
text-align: center;
border-radius: 5px;
background: #4584b1;
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
</div>
</body>
</html>
div 요소는 block 요소
이므로 수직 정렬
된다. 이를 수평 정렬하려면 자식요소(flex-item)를 inline-block
으로 지정하거나 float
프로퍼티를 지정한다.
.flex-item {
display: inline-block;
/* or */
float: left;
}
이때 각 자식 요소을 부모 요소 내에서 정렬하기 위해서는 각 자식 요소의 너비를 %로 지정하는 등 번거로운 처리가 필요하다. 자식 요소의 사이즈가 불명확하거나 동적으로 변화할 때에는 더욱 처리가 복잡해 진다.
.flex-container {
display: flex;
justify-content: space-around;
}
위처럼 Flexbox
를 사용하면 기존에 방식에 비해 매우 간단히 레이아웃을 처리할 수 있다.
Flexbox의 장점
Flexbox 레이아웃은 flex item
이라 불리는 복수의 자식 요소와 이들을 내포하는 flex-container
부모 요소로 구성된다.
flexbox를 사용하기 위해서 HTML 부모 요소의 display
속성에 flex
를 지정한다.
.flex-container {
display: flex;
}
부모 요소가 inline 요소
인 경우 inline-flex
를 지정한다.
.flex-container {
display: inline-flex;
}
flex
또는 inline-flex
는 부모 요소에 반드시 지정해야하는 유일한 속성
이며 자식 요소는 자동적으로 flex item
이 된다.
flex-direction
속성은 flex 컨테이너의주축(main axis) 방향을 설정
한다.
flex-direction: row;
좌에서 우로(ltr) 수평 배치된다. flex-direction 속성의 기본값
이다.
.flex-container {
flex-direction: row;
}
flex-direction: row-reverse;
우에서 좌로(rtl) 수평 배치된다.
.flex-container {
flex-direction: row-reverse;
}
flex-direction: column;
위에서 아래로 수직 배치된다.
.flex-container {
flex-direction: column;
}
flex-direction: column-reverse;
아래에서 위로 수직 배치된다.
.flex-container {
flex-direction: column-reverse;
}
flex-wrap
속성은 flex 컨테이너의 복수 flex item을1행
으로 또는복수행
으로 배치한다.flex-wrap
속성은flex 컨테이너의 width
보다flex item들의 width
의 합계가 더 큰 경우,한줄로 표현할 것
인지,여러줄로 표현할 것
인지를 지정한다.
flex-wrap: nowrap;
flex item을 개행하지 않고 1행에 배치한다. flex-wrap 속성의 기본값
이다. 각 flex item의 폭은 flex container에 들어갈 수 있는 크기로 축소된다.
.flex-container {
flex-wrap: nowrap;
}
하지만 flex item들의 width
의 합계가 flex 컨테이너의 width
보다 큰 경우 flex 컨테이너를 넘치게 된다.
이때 overflow: auto;
를 지정하면 가로 스크롤이 생기며 컨테이너를 넘치지 않는다.
<!DOCTYPE html>
<html>
<head>
<title>Flexbox</title>
<meta charset="UTF-8">
<style>
.flex-container {
width: 500px;
margin: 10px;
padding: 15px;
border-radius: 5px;
background: #60B99A;
display: flex;
flex-wrap: nowrap;
overflow: auto;
}
.flex-item {
margin: 10px;
padding: 20px;
color: #fff;
text-align: center;
border-radius: 5px;
background: #4584b1;
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item">11111111</div>
<div class="flex-item">22222222</div>
<div class="flex-item">33333333</div>
<div class="flex-item">44444444</div>
<div class="flex-item">55555555</div>
</div>
</body>
</html>
flex-wrap: wrap;
flex item들의 width
의 합계가 flex 컨테이너의 width
보다 큰 경우, flex item을 복수행에 배치
한다. 기본적으로 좌에서 우로, 위에서 아래로 배치된다.
.flex-container {
flex-wrap: wrap;
}
flex-wrap: wrap-reverse;
flex-wrap: wrap;
과 동일하나 아래에서 위로 배치된다.
.flex-container {
flex-wrap: wrap-reverse;
}
flex-flow 속성은 flex-direction 속성과 flex-wrap 속성을 설정하기 위한 shorthand이다. 기본값은 row nowrap
이다.
.flex-container {
flex-flow: <flex-direction> || <flex-wrap>;
}
flex container의 main axis를 기준으로 flex item을
수평 정렬
한다.
justify-content: flex-start;
main start(좌측)를 기준
으로 정렬한다. justify-content 속성의 기본값이다.
.flex-container {
justify-content: flex-start;
}
justify-content: flex-end;
main end(우측)를 기준
으로 정렬한다.
.flex-container {
justify-content: flex-end;
}
justify-content: center;
flex container의 중앙
에 정렬한다.
.flex-container {
justify-content: center;
}
justify-content: space-between;
첫번째와 마지막 flex item은 좌우 측면
에 정렬되고 나머지와 균등한 간격
으로 정렬된다.
.flex-container {
justify-content: space-between;
}
justify-content: space-around;
모든 flex item은 균등한 간격으로 정렬된다.
.flex-container {
justify-content: space-around;
}
flex item을 flex container의
수직 방향(cross axis)
으로 정렬한다. align-items 속성은 모든 flex item에 적용된다.
align-items: stretch;
모든 flex item은 flex container의 높이(cross start에서 cross end까지의 높이)에 꽉찬 높이
를 갖는다. align-items 속성의 기본값이다.
.flex-container {
align-items: stretch;
}
align-items: flex-start;
모든 flex item은 flex container의 cross start 기준
으로 정렬된다.
.flex-container {
align-items: flex-start;
}
align-items: flex-end;
모든 flex item은 flex container의 cross end 기준
으로 정렬된다.
.flex-container {
align-items: flex-end;
}
align-items: center;
모든 flex item은 flex container의 cross axis의 중앙
에 정렬된다.
.flex-container {
align-items: center;
}
align-items: baseline;
모든 flex item은 flex container의 baseline을 기준
으로 정렬된다.
.flex-container {
align-items: baseline;
}
flex container의 cross axis를 기준으로 flex item을 수직 정렬한다. 참고로 justify-content 속성은 flex container의 main axis를 기준으로 flex item을 수평 정렬한다.
align-content: stretch;
모든 flex item은 flex item의 행 이후에 균등하게 분배된 공간
에 정렬되어 배치된다. align-content 속성의 기본값
이다.
.flex-container {
align-content: stretch;
}
align-content: flex-start;
모든 flex item은 flex container의 cross start 기준
으로 stack
정렬된다.
.flex-container {
align-content: flex-start;
}
align-content: flex-end;
모든 flex item은 flex container의 cross end 기준
으로 stack
정렬된다.
.flex-container {
align-content: flex-end;
}
align-content: center;
모든 flex item은 flex container의 cross axis의 중앙
에 stack
정렬된다.
.flex-container {
align-content: center;
}
align-content: space-between;
첫번째 flex item의 행
은 flex container의 상단
에 마지막 flex item의 행
은 flex container의 하단
에 배치되며 나머지 행은 균등 분할된 공간
에 배치 정렬된다.
.flex-container {
align-content: space-between;
}
align-content: space-around;
모든 flex item은 균등 분할된 공간
내에 배치 정렬된다.
.flex-container {
align-content: space-around;
}
float
clear
vertical-align
속성은 flex item에 영향을 주지 않는다.
flex item의
배치 순서를 지정
한다. HTML 코드를 변경하지 않고 order 속성값을 지정하는 것으로 간단히 재배치할 수 있다.
기본 배치 순서는 flex container에 추가된 순서이다. 기본값은 0
이다.
.flex-item {
order: 정수값;
}
flex item의 너비에 대한 확대 인자(flex grow factor)를 지정한다. 기본값은
0
이고음수값은 무효
하다.
.flex-item {
flex-grow: 양의 정수값;
}
모든 flex item이 동일한 flex-grow 속성값을 가지면 모든 flex item은 동일한 너비를 갖는다.
두번째 flex item의 flex-grow 속성값을 3으로 지정하면 다른 flex item보다 더 넓은 너비를 갖는다.
flex item의 너비에 대한 축소 인자(flex shrink factor)를 지정한다. 기본값은
1
이고음수값은 무효
하다.0
을 지정하면 축소가 해제되어원래의 너비를 유지
한다.
기본적으로 모든 flex item은 축소된 상태로 지정(기본값 1)하고 두번째 flex item만 축소를 해제(flex-shrink: 0;)하면 원래의 너비를 유지한다.
.flex-item {
flex-shrink: 양의 정수값;
}
flex item의
너비 기본값
을px
%
등의 단위로 지정한다. 기본값은auto
이다.
.flex-item {
flex-basis: auto | <width>;
}
flex-grow
flex-shrink
flex-basis
속성의 shorthand이다. 기본값은 0 1 auto이다.
.flex-item {
flex: none | auto | [ <flex-grow> <flex-shrink>? || <flex-basis> ];
//기본값
flex: 0 1 auto
}
align-items 속성보다 우선하여 개별 flex item을 정렬한다. 기본값은
auto
이다.
.flex-item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
3번째, 4번째 flex item은 align-self
속성값이 우선 적용되어 정렬된다.
https://codepen.io/enxaneta/pen/adLPwv
정렬 대상 요소의 부모 요소에
text-align: center;
를 지정한다.
.container {
text-align: center;
}
정렬 대상 요소에
너비를 명시적으로 지정
하고margin-right
와margin-left
프로퍼티에auto
를 지정한다. 정렬 대상 요소에 너비를 명시적으로 지정하지 않으면 너비는full width
가 되므로 중앙 정렬이 필요없다.
.item {
width: 200px;
margin: 20px auto;
}
복수의 block 요소는 기본적으로 수직 정렬된다.
수평정렬
하기 위해서는정렬 대상 block 요소
를inline-block
요소로 변경한 후 부모 요소에text-align: center;
를 지정한다.
정렬 대상 요소
에width
를 지정하지 않으면 콘텐츠에 너비에 맞추어 너비가 결정되므로명시적으로 너비를 지정
한다.
.container {
text-align: center;
}
.item {
width: 150px;
display: inline-block;
}
flexbox
를 사용할 수도 있다. 정렬 대상의부모 요소
에 선언한다.
.flex-center {
display: flex;
justify-content: center;
}
정렬 대상의 부모 요소에
padding-top
과padding-bottom
프로퍼티값을 동일하게 적용한다.
.container {
padding: 50px;
}
padding
을 사용할 수 없는 경우, 요소의 height
와 line-height
프로퍼티값을 동일하게 적용
한다. 단 이 방법은 행간이 지나치게 넓어지거나 Click Dead Zone 이슈
가 발생하는 등 여러 줄의 텍스트
에는 사용할 수 없다.
.container {
height: 100px;
line-height: 100px;
}
여러 줄의 텍스트의 경우,
padding-top
과padding-bottom
프로퍼티값을 동일하게 적용하는 방법도 가능하다.
또 다른 방법으로 vertical-align 프로퍼티를 사용한 방법도 가능하다. 이 방법은 table 속성을 사용하여야 한다.
.parent {
display: table;
height: 100px;
}
.child {
display: table-cell;
vertical-align: middle;
}
vertical-align
프로퍼티를 사용하는 방법은table
프로퍼티를 사용하여야 하므로 번거로울 수 있다. 좀 더 간단한 방법은flexbox
를 사용하는 것이다.
.container {
display: flex;
justify-content: center;
flex-direction: column;
height: 400px;
}
부모 요소를 기준으로
절대 위치
를 지정한다.
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
height: 100px;
/*요소의 높이(100px)의 반 만큼 위로 이동*/
margin-top: -50px;
}
부모 요소를 기준으로
절대 위치
를 지정한다.
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
/*요소의 높이의 반(50%) 만큼 위로 이동*/
transform: translateY(-50%);
}
부모 요소에 Flexbox layout
을 지정한다.
.parent {
display: flex;
/*위에서 아래로 수직 배치*/
flex-direction: column;
/*중앙정렬*/
justify-content: center;
}
요소의 너비와 높이가 고정되어 있는 경우, 요소의 너비와 높이가 불확정 상태의 경우 모두 사용 가능한 방법이다
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
/*요소의 높이/너비의 반(50%)만큼 위/왼쪽으로 이동*/
transform: translate(-50%, -50%);
}
Flexbox를 사용한 방법
.parent {
display: flex;
justify-content: center;
align-items: center;
}
<!DOCTYPE html>
<html>
<head>
<style>
.container {
width: 350px;
border: 1px solid red;
}
</style>
</head>
<body>
<div class="container">
<img src="http://via.placeholder.com/350x150/f5ab3d/fff">
</div>
</body>
</html>
컨테이너 요소로 img 요소를 래핑하면 img 요소 아래에 의도하지 않은 여분의 공간이 패딩된다.
image
요소는inline
요소이다. 다시 말해 image 요소는텍스트
로 취급된다.
<!DOCTYPE html>
<html>
<head>
<style>
.container {
width: 435px;
border: 1px solid red;
}
</style>
</head>
<body>
<div class="container">
Typography
<img src="http://via.placeholder.com/350x150/f5ab3d/fff">
</div>
</body>
</html>
위 그림과 같이 image 요소에도 디센더
가 적용되어 여분의 공간이 발생한다.
첫째, image 요소를
block 요소
로 전환하면 더 이상 텍스트로 취급되지 않는다.
<!DOCTYPE html>
<html>
<head>
<style>
.container {
width: 350px;
border: 1px solid red;
}
img {
display: block;
}
</style>
</head>
<body>
<div class="container">
<img src="http://via.placeholder.com/350x150/f5ab3d/fff">
</div>
</body>
</html>
하지만 이 방법은 image 요소를 block 요소로 전환할 수 없는 레이아웃에서는 사용할 수 없다.
둘째, inline 요소에 사용할 수 있는
vertical-align
프로퍼티를 사용하는 법이 있다.
vertical-align
프로퍼티의 기본값은baseline
인데 이를 변경하여 이미지표시 위치를 조정
하는 것이다.
<!DOCTYPE html>
<html>
<head>
<style>
.container {
width: 350px;
border: 1px solid red;
}
img {
vertical-align: bottom;
}
</style>
</head>
<body>
<div class="container">
<img src="http://via.placeholder.com/350x150/f5ab3d/fff">
</div>
</body>
</html>
본 포스트는 [웹 프로그래밍 튜토리얼 PoiemaWeb의 CSS3] 를 정독하며 정리한 글입니다.