CSS3

블로그 이사 완료·2022년 12월 3일
0
post-thumbnail

📍 Syntax : 문법

#1. 셀렉터 (Selector, 선택자)

CSS 는 HTML요소 의 style(design, layout etc)을 정의하는데 사용된다.이를 위해서 선행되어야하는 것은 스타일을 적용하고자 하는 HTML 요소를 선택 할 수 있어야 한다. 셀렉터 는 스타일을 적용하고자 하는 HTML요소 를 선택하기 위해 CSS에서 제공하는 수단이다.

위와 같은 구문을 Rule Set 이라 하며 셀렉터 에 의해 선택된 특정 HTML요소 를 어떻게 렌더링 할 것인지 브라우저에 지시하는 역할을 한다. 위의 CSS Rule set은 HTML문서 에 속해 있는 셀렉터 를 통해 모든 h1 요소 를 선택 한 후 선택된 h1 요소의 스타일을 선언 블록에서 정의하고 있다. 이와 같은 Rule Set의 집합을 스타일시트(Style Sheet) 라 한다.

#2. 프로퍼티 (Property / 속성)

셀렉터HTML요소 를 선택하고 {} 내에 프로퍼티(속성) 을 지정하는 것으로 다양한 style을 정의 할 수 있다. 프로퍼티는 표준 스펙으로 이미 지정되어 있는 것을 사용하여야하며 사용자가 임의로 정의할 수 없다. 여러 개의 프로퍼티를 연속해서 지정할 수 있으며 세미콜론(;) 으로 구분한다.

p {
  color: ...;
  font-size: ...;
}

#3. 값 (Value / 속성값)

셀렉터 로 지정한 HTML요소 에 style을 적용하기 위해 프로퍼티를 사용했다. 프로퍼티의 값은 해당 프로퍼티에 사용할 수 있는 값을 키워드 크기 단위 색상 표현 단위 등의 특정 단위 로 지정하여야 한다.

p {
  color: orange;
  font-size: 16px;
}

#4. HTML과 CSS의 연동

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; }

#4.2 Embedding style

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>

#4.3 Inline style

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>

#5. Reset CSS 사용하기

모든 웹 브라우저는 디폴트 스타일(브라우저가 내장하고 있는 기본 스타일)을 가지고 있어 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;
}

ㅤㅤ

📍 Selector : 셀렉터

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; }

#1. 전체 셀렉터 (Universal Selector)

패턴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>

#2. 태그 셀렉터 (Type Selector)

패턴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>

#3. ID 셀렉터 (ID Selector)

패턴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>

#4. 클래스 셀렉터 (Class Selector)

패턴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>

#5. 어트리뷰트 셀렉터 (Attribute Selector)

패턴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>

#6. 복합 셀렉터 (Combinator)

#6.1 후손 셀렉터 (Descendant Combinator)

자신의 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>

#6.2 자식 셀렉터 (Child Combinator)

자손 셀렉터는 셀렉터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>

#6.3 형제(동위) 셀렉터 (Sibling Combinator)

형제(동위) 셀렉터는 형제 관계(동위 관계) 에서 뒤에 위치하는 요소를 선택할 때 사용한다.

#6.3.1 인접 형제 셀렉터(Adjacent Sibling Combinator)

셀렉터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>

#6.3.2 일반 형제 셀렉터(General Sibling Combinator)

셀렉터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>

#7. 가상 클래스 셀렉터 (Pseudo-Class Selector)

가상 클래스는 요소의 특정 상태에 따라 스타일을 정의할 때 사용된다.

  • 마우스가 올라와 있을때
  • 링크를 방문했을 때와 아직 방문하지 않았을 때
  • 포커스가 들어와 있을 때

이러한 특정 상태에는 원래 클래스가 존재하지 않지만 가상 클래스를 임의로 지정하여 선택하는 방법이다. 가상 클래스는 마침표(.) 대신 콜론(:) 을 사용한다. 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-classDescription
: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>

#7.2 UI 요소 상태 셀렉터(UI element states pseudo-classes)

pseudo-classDescription
: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>

#7.3 구조 가상 클래스 셀렉터(Structural pseudo-classes)

pseudo-classDescription
: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-classDescription
:nth-child(n)셀렉터에 해당하는 모든 요소 중 앞에서 n번째 자식인 요소를 선택한다.
:nth-last-child(n)셀렉터에 해당하는 모든 요소 중 뒤에서 n번째 자식인 요소를 선택한다.

n은 0부터 시작하는 정수이다.

n2n+12n-13n-23n+1-n+5
01-1-215
131144
253473
3757102
49710131
511913160

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-classDescription
: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>

#7.4 부정 셀렉터(Negation pseudo-class)

pseudo-classDescription
: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>

#7.5 정합성 체크 셀렉터(validity pseudo-class)

pseudo-classDescription
: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>

#8. 가상 요소 셀렉터 (Pseudo-Element Selector)

가상 요소는 요소의 특정 부분에 스타일을 적용하기 위하여 사용된다. 특정 부분이란 예를 들어 다음과 같다.

  • 요소 콘텐츠의 첫글자 또는 첫줄
  • 요소 콘텐츠의 앞 또는 뒤

가상 요소에는 두개의 콜론(::)을 사용한다. CSS 표준에 의해 미리 정의된 이름이 있기 때문에 임의의 이름을 사용할 수 없다.

selector::pseudo-element {
  property:value;
}
pseudo-elementDescription
::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>


ㅤㅤ

📍 Units : 프로퍼티 값의 단위

CSS 프로퍼티에는 키워드, 크기 단위, 색상 표현 단위 등의 특정 단위를 갖는 값을 지정한다.

#1. 키워드

각 프로퍼티에 따라 사용할 수 있는 키워드가 존재한다.예를 들어 display 의 프로퍼티의 값으로 사용할 수 있는 키워드는 block inline inline-block none이 있다.

#2. 크기 단위

cm, mm, inch 등의 단위도 존재하나 CSS에서 사용하는 대표적인 크기 단위는 px em % 이다. px은 절대값 이고 em, %는 상대값 이다. 프로퍼티 값이 0인 경우, 단위를 생략할 수 있다.

대부분 브라우저의 폰트 사이즈 기본값은 16px, 1em, 100%이다.

#2.1 px

px 은 픽셀(화소) 단위이다. 1px은 화소 1개 크기를 의미한다.

22인치 LCD 모니터의 경우 해상도가 1680 1050 인데 이것은 가로에 1680개의 픽셀, 세로에 1050개의 픽셀을 가진다는 의미이다. 200만 화소(픽셀)의 디지털 카메라로 찍은 사진은 1600 1200 = 1,920,000으로 통상 200만 화소라 한다.

스크린에서 확대한 픽셀. 각 픽셀들은 적색(R) 녹색(G) 청색(B) 요소를 가지고 있다. 픽셀은 디바이스 해상도에 따라 상대적인 크기를 갖는다.

이와 같이 디바이스 별로 픽셀(화소)의 크기는 제각각이기 때문에 픽셀을 기준으로 하는 단위는 명확하지 않다. 따라서 대부분의 브라우저는 1px1/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>

#2.2 %

% 는 백분률 단위의 상대 단위이다. 요소에 지정된 사이즈(상속된 사이즈나 디폴트 사이즈)에 상대적인 사이즈를 설정한다.

<!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>

#2.3 em

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>

#2.4 rem

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 */
}
  • Reset CSS를 사용하여 사전에 html 요소의 font-size 지정이 필요하다. font-size 미지정 시에는 16px가 적용된다.

#2.5 Viewport 단위(vh, vw, vmin, vmax)

반응형 웹디자인은 화면의 크기에 동적으로 대응하기 위해 % 단위를 자주 사용한다. 하지만 % 단위는 em 과 같이 상속에 의해 부모 요소에 상대적 영향을 받는다.

Viewport단위는 상대적인 단위로 viewport 를 기준으로 한 상대적 사이즈를 의미한다.

단위Description
vwviewport 너비의 1/100
vhviewport 높이의 1/100
vminviewport 너비 또는 높이 중 작은 쪽의 1/100
vmaxviewport 너비 또는 높이 중 큰 쪽의 1/100

예를 들어 viewport 너비가 1000px, 높이가 600px인 경우,

  • 1vw : viewport 너비 1000px의 1%인 10px
  • 1vh : viewport 높이 600px의 1%인 6px
  • vmin : viewport 높이 600px의 1%인 6px
  • vmax : viewport 너비 1000px의 1%인 10px
<!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>

#3. 색상 표현 단위

색상을 지정하기 위해 키워드(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)

ㅤㅤ

📍 Box Model : 박스모델

모든 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>


#1. width / height 프로퍼티

width와 height 프로퍼티는 요소의 너비와 높이를 지정하기 위해 사용된다.

이때 지정되는 요소의 너비와 높이는 콘텐츠 영역 을 대상으로 한다. box-sizing 프로퍼티에 기본값인 content-box가 적용되었기 때문이다. box-sizing 프로퍼티에 border-box 를 적용하면 콘텐츠 영역, padding, border가 포함된 영역을 width / height 프로퍼티의 대상으로 지정할 수 있다.

  • 만일 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 등)는 상속되지 않는다.

#2. margin / padding 프로퍼티

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>

  • top, right, bottom, left 4방향의 프로퍼티를 각각 지정하지 않고 margin, padding 1개의 프로퍼티만으로 4방향의 프로퍼티를 한번에 지정할 수 있다.

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)을 유지한다.

#3. border 프로퍼티

#3.1 border-style

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>

#3.2 border-width

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>

#3.3 border-color

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>

#3.4 border-radius

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>

#3.5 border

border 프로퍼티는 border-widthborder-styleborder-color를 한번에 설정하기 위한 shorthand 프로퍼티이다.

/* Syntax */
border: border-width border-style border-color;
p {
  /* border-width border-style border-color */
  border: 5px solid red;
}

#4. box-sizing 프로퍼티

  • box-sizing 프로퍼티는 width, height 프로퍼티의 대상 영역을 변경할 수 있다.
  • box-sizing 프로퍼티의 기본값은 content-box 이다. 이는 width, height 프로퍼티의 대상 영역이 content 영역을 의미한다.
  • box-sizing 프로퍼티의 값을 border-box 로 지정하면 마진을 제외한 박스 모델 전체를
    width, height 프로퍼티의 대상 영역으로 지정할 수 있어서 CSS Layout을 직관적으로 사용할 수 있게 한다.
키워드설명
content-boxwidth, height 프로퍼티 값은 content 영역을 의미한다. (기본값)
border-boxwidth, 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 : display / visibility / opacity 프로퍼티

#1. display 프로퍼티

display 프로퍼티는 layout 정의에 자주 사용되는 중요한 프로퍼티이다.

프로퍼티값 키워드설명
blockblock 특성을 가지는 요소(block 레벨 요소)로 지정
inlineinline 특성을 가지는 요소(inline 레벨 요소)로 지정
inline-blockinline-block 특성을 가지는 요소(inline-block 레벨 요소)로 지정
none해당 요소를 화면에 표시하지 않는다 (공간조차 사라진다)

모든 HTML 요소는 아무런 CSS를 적용하지 않아도 기본적으로 브라우저에 표현되는 디폴트 표시값을 가진다. HTML 요소는 block 또는 inline 특성을 갖는다.

display 프로퍼티는 상속되지 않는다.

#1.1 block 레벨 요소

block 레벨 요소 는 아래와 같은 특징을 갖는다.

  • 항상 새로운 라인에서 시작한다.
  • 화면 크기 전체의 가로폭을 차지한다. (width: 100%)
  • width height margin padding 프로퍼티 지정이 가능하다.
  • block 레벨 요소 내에 inline 레벨 요소를 포함할 수 있다
  • block 레벨 요소 예
    • div
    • h1 ~ h6
    • p
    • ol
    • ul
    • li
    • hr
    • table
    • form
<!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>

#1.2 inline 레벨 요소

inline레벨 요소 는 아래와 같은 특징을 갖는다.

  • 새로운 라인에서 시작하지 않으며 문장의 중간에 들어갈 수 있다. 즉, 줄을 바꾸지 않고 다른 요소와 함께 한 행에 위치한다.
  • content 의 너비만큼 가로폭을 차지한다.
  • width height margin-top margin-bottom 프로퍼티를 지정할 수 없다. 상, 하 여백은 line-height 로 지정한다.
  • inline 레벨 요소 뒤에 공백(엔터, 스페이스 등)이 있는 경우, 정의하지 않은 space(4px)가 자동 지정된다.
  • inline 레벨 요소 내에 block 레벨 요소를 포함할 수 없다. inline 레벨 요소는 일반적으로 block 레벨 요소에 포함되어 사용된다.
  • inline 레벨 요소 예
    • span
    • a
    • strong
    • img
    • br
    • input
    • select
    • textarea
    • button
<!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>

#1.3 inline-block 레벨 요소

blockinline 레벨 요소의 특징을 모두 갖는다. inline 레벨 요소와 같이 한 줄에 표현되면서 width height margin 프로퍼티를 모두 지정할 수 있다.

  • 기본적으로 inline 레벨 요소와 흡사하게 줄을 바꾸지 않고 다른 요소와 함께 한 행에 위치시킬 수 있다.
  • block 레벨 요소처럼 width height margin padding 프로퍼티를 모두 정의할 수 있다. 상, 하 여백을 marginline-height 두가지 프로퍼티 모두를 통해 제어할 수 있다.
  • content 의 너비만큼 가로폭을 차지한다.
  • inline-block 레벨 요소 뒤에 공백(엔터, 스페이스 등)이 있는 경우, 정의하지 않은 space(4px)가 자동 지정된다.
<!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>

#2. visibility 프로퍼티

visibility 프로퍼티는 요소를 보이게 할 것인지 보이지 않게 할 것인지를 정의한다. 즉, 요소의 렌더링 여부를 결정한다.

프로퍼티값 키워드설명
visible해당 요소를 보이게 한다 (기본값)
hidden해당 요소를 보이지 않게 한다. 
display: none; 은 해당 요소의 공간까지 사라지게 하지만 visibility: hidden; 은 해당 요소의 공간은 사라지지 않고 남아있게 된다.
collapsetable 요소에 사용하며 행이나 열을 보이지 않게 한다.
nonetable 요소의 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>

#3. opacity 프로퍼티

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>


ㅤㅤ

📍 Background : 백그라운드

#1. background-image 프로퍼티

요소에 배경 이미지를 지정한다.

<!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>

#2. background-repeat 프로퍼티

배경 이미지의 반복을 지정한다. 수직, 수평 또는 수직과 수평 모두의 반복을 지정할 수 있다.

설정된 이미지의 크기가 화면보다 작으면 자동으로 이미지가 반복 출력되어 화면을 채우게 된다. 이것은 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>

#3. background-size 프로퍼티

배경 이미지의 사이즈를 지정한다. 배경 이미지의 고유 비율을 유지하기 때문에 설정에 따라 이미지의 일부가 보이지 않을 수 있다.

프로퍼티값은 px % cover contain 등을 사용한다. 배경이미지의 width height를 모두 설정할 수 있다. 이때 첫번째 값은 width 두번째 값은 height 를 의미한다.

  • 하나의 값만을 지정한 경우, 지정한 값은 width를 의미하게 되며 height는 auto로 지정된다.

px값 지정
배경이미지 크기가 지정된 px값 그대로 설정된다. 첫번째 값은 width, 두번째 값은 height를 의미한다.

.bg {
  background-size: 700px 500px;
}

Result

%값 지정
배경이미지 크기가 지정된 %값에 비례하여 설정된다. 첫번째 값은 width, 두번째 값은 height를 의미한다.
화면을 줄이거나 늘리면 배경이미지의 크기도 따라서 변경되어 찌그러지는 현상이 나타난다.

.bg {
  background-size: 100% 100%;
}

Result

cover 지정
배경이미지의 크기 비율을 유지한 상태에서 부모 요소의 width height큰 값 에 배경이미지를 맞춘다. 따라서 이미지의 일부가 보이지 않을 수 있다.

.bg {
  background-size: cover;
}

Result

contain 지정
배경이미지의 크기 비율을 유지한 상태에서 부모 요소의 영역에 배경이미지가 보이지 않는 부분없이 전체가 들어갈 수 있도록 이미지 스케일을 조정한다.

.bg {
  background-size: contain;
}

Result

width, height의 프로퍼티값은 공백으로 구분하여야 한다. 프로퍼티값을 쉼표로 구분하면 다른 배경이미지의 너비를 지정하는 것으로 인식되기 때문에 주의가 필요하다.

body {
  background-image: url("front.png"), url("back.png");
  background-repeat: no-repeat, no-repeat;
  background-size: 100%, 500px;
}

#4. background-attachment 프로퍼티

일반적으로 화면을 스크롤하면 배경 이미지도 함께 스크롤된다. 화면이 스크롤되더라도 배경이미지는 스크롤되지 않고 고정되어 있게 하려면 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>

Result

#5. background-position 프로퍼티

일반적으로 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>

Result

#6. background-color 프로퍼티

background-color 프로퍼티는 요소의 배경 색상을 지정한다. 색상값 또는 transparent 키워드를 지정할 수 있다.

.bg-col-white {
  background-color: rgb(255, 255, 255);
}

.bg-col-red {
  background-color: red;
}

#7. background Shorthand

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>


ㅤㅤ

📍 Font & Text : 폰트와 텍스트

#1. font-size 프로퍼티

텍스트의 크기를 정의한다.

<!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>

#2. font-family 프로퍼티

폰트를 지정한다. 컴퓨터에 해당 폰트가 설치되어 있지 않으면 적용되지 않는다.

폰트는 여러 개를 동시에 지정이 가능하다. 첫번째 지정한 폰트가 클라이언트 컴퓨터에 설치되어 있지 않은 경우, 다음에 지정된 폰트를 적용한다.
마지막에 지정하는 폰트는 대부분의 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>

#3. font-style / font-weight 프로퍼티

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>

#4. font Shorthand

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;

#5. line-height 프로퍼티

텍스트의 높이를 지정한다. 텍스트 수직 정렬에도 응용되어 사용된다.

<!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>

#6. letter-spacing 프로퍼티

글자 사이의 간격을 지정한다.

<!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>

#7. text-align 프로퍼티

텍스트의 수평 정렬을 정의한다.

<!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;을 지정한다면 중앙 정렬이 가능하다.

#8. text-decoration 프로퍼티

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>

#9. white-space 프로퍼티

white space는 공백(space), 들여쓰기(tab), 줄바꿈(line break)을 의미한다.

html은 기본적으로 연속된 공백(space) 들여쓰기(tab)는 1번만 실행되며 줄바꿈(line break) 은 무시된다. 또한 텍스트는 부모의 가로 영역을 벗어나지 않고 자동 줄바꿈(wrap) 된다. white-space 프로퍼티는 이러한 기본 동작을 제어하기 위한 프로퍼티이다.

프로퍼티값line breakspace/tabwrapping(자동줄바꿈)
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">&laquo;</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">&raquo;</button>
  </div>
</body>
</html>

#10. text-overflow 프로퍼티

부모 영역을 벗어난 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>

#11. word-wrap 프로퍼티

한 단어의 길이가 길어서 부모 영역을 벗어난 텍스트의 처리 방법을 정의한다.

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>

#12. word-break 프로퍼티

한 단어의 길이가 길어서 부모 영역을 벗어난 텍스트의 처리 방법을 정의한다.

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 : 요소의 위치 정의

#1. position 프로퍼티

position 프로퍼티는 요소의 위치를 정의한다. top bottom left right 프로퍼티와 함께 사용하여 위치를 지정한다.

#1.1 static (기본위치)

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>

Result

#1.2 relative (상대위치)

기본 위치(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>

Result

위 코드를 보면 parent 클래스의 자식인 relative-box 클래스 요소의 width height가 부모 요소와 동일하다.

이는 상속에 의한 것이 아니라 relative 를 적용한 요소는 좌표 프로퍼티가 적용되는 것만 다를 뿐 그 이외는 static 을 지정했을 때와 동일하게 동작하기 때문이다. 즉, width100% 가 적용되어 부모 요소의 width와 동일 한 값을 갖게된 것이고, hightauto 가 적용되지만 line-height: 150px 이 적용되어 부모 요소와 hight가 동일 하게 된 것이다.

#1.3 absolute (절대위치)

부모 요소 또는 가장 가까이 있는 조상 요소(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>

Result

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>

Result

#1.4 fixed (고정위치)

부모 요소와 관계없이 브라우저의 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>

Result

#2. z-index 프로퍼티

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>

#3. overflow 프로퍼티

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 : 요소 정렬

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요소를 왼쪽으로 이동시킨다.

#1. 정렬

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;
}

#2. width

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 클래스 요소가 그 위에 위치한다.

#3. float 프로퍼티 관련 문제 해결 방법

#3.1 float 프로퍼티가 선언된 요소와 float 프로퍼티가 선언되지 않은 요소간 margin이 사라지는 문제

두 요소는 차례대로 정렬된 것처럼 보이지만 사실은 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 프로퍼티는 선언하지 않아도 되지만 너비가 최소화 된다.

#3.2 float 프로퍼티가 선언된 자식 요소를 포함하는 부모 요소의 높이가 정상적으로 반영되지 않는 문제

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>


ㅤㅤ

📍 Inherit & Cascading : 스타일의 상속과 적용 우선 순위

#1. 상속(Inheritance)

상속 이란 상위(부모, 조상) 요소에 적용된 프로퍼티를 하위(자식, 자손) 요소가 물려 받는 것을 의미한다. 상속 기능이 없다면 각 요소의 Rule set에 프로퍼티를 매번 각각 지정해야 한다. 하지만 모든 프로퍼티가 상속되는 것은 아니다. 프로퍼티 중에는 상속이 되는 것과 되지 않는 것이 있다.

PropertyInherit
width / heightno
marginno
paddingno
borderno
box-sizingno
displayno
visibilityyes
opacityyes
backgroundno
fontyes
coloryes
line-heightyes
text-alignyes
vertical-alignno
text-decorationno
white-spaceyes
positionno
top/right/bottom/leftno
z-indexno
overflowno
floatno
<!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>

#2. 캐스캐이딩(Cascading)

요소는 하나 이상의 CSS 선언에 영향을 받을 수 있다. 이때 충돌을 피하기 위해 CSS 적용 우선순위 가 필요한데 이를 캐스캐이딩(Cascading Order) 이라고 한다. 캐스캐이딩에는 다음과 같이 세가지 규칙이 있다.

중요도
CSS가 어디에 선언 되었는지 에 따라서 우선순위가 달라진다.

명시도
대상을 명확하게 특정 할수록 명시도가 높아지고 우선순위가 높아진다.

선언순서
선언된 순서 에 따라 우선 순위가 적용된다. 즉, 나중에 선언된 스타일이 우선 적용된다.

#2.1 중요도

CSS가 어디에 선언 되었는지에 따라서 우선순위가 달라진다.

  1. head 요소 내의 style 요소
  2. head 요소 내의 style 요소 내의 @import 문
  3. <link> 로 연결된 CSS 파일
  4. <link> 로 연결된 CSS 파일 내의 @import 문
  5. 브라우저 디폴트 스타일시트
/* 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>

#2.2 명시도

대상을 명확하게 특정할수록 명시도가 높아지고 우선순위가 높아진다.

!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>

#2.3 선언순서

선언된 순서에 따라 우선 순위가 적용된다. 즉, 나중에 선언된 스타일이 우선 적용된다.

<!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>


ㅤㅤ

📍 Vendor Prefix : 벤더 프리픽스

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 */
}

브라우저 별 벤더 프리픽스

BrowserVendor 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>

ㅤㅤ

📍 Shadow : 그림자

#1. text-shadow

텍스트에 그림자 효과를 부여하는 프로퍼티이다.

선택자 { text-shadow: Horizontal-offset Vertical-offset Blur-Radius Shadow-Color; }
프로퍼티 값단위설명생략
Horizontal-offsetpx그림자를 텍스트의 오른쪽으로 지정값만큼 이동시킨다
Vertical-offsetpx그림자를 텍스트의 아래로 지정값만큼 이동시킨다
Blur-Radiuspx그림자의 흐림정도를 지정한다. 지정값만큼 그림자가 커지고 흐려진다. (양수)가능
Shadow-Colorcolor그림자의 색상을 지정한다가능
<!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>

PropertyChromeEdgeIEFirefoxSafariOpera
text-shadow412103.549.5

#2. box-shadow

요소에 그림자 효과를 부여하는 프로퍼티이다.

선택자 { box-shadow: Inset Horizontal-offset Vertical-offset Blur-Radius Spread Shadow-Color; }
프로퍼티 값단위설명생략
Insetinsetinset 키워드를 지정하면 그림자가 요소 안쪽에 위치한다.가능
Horizontal-offsetpx그림자를 텍스트의 오른쪽으로 지정값만큼 이동시킨다
Vertical-offsetpx그림자를 텍스트의 아래로 지정값만큼 이동시킨다
Blur-Radiuspx그림자의 흐림정도를 지정한다. 지정값만큼 그림자가 커지고 흐려진다. (양수)가능
Spreadpx그림자를 더 크게 확장시킨다. (음수, 양수)가능
Shadow-Colorcolor그림자의 색상을 지정한다가능
<!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 : 그라디언트

그레이디언트(Gradient)는 2가지 이상의 색상을 혼합하여 부드러운 색감의 배경 등을 생성하는 것이다.

CSS3가 이 기능을 제공하기 이전에는 포토샵 등의 소프트웨어를 사용하여 그레이디언트 효과의 이미지를 제작하여 사용하였다. 그러나 이러한 방법은 이미지 다운로드 에 시간이 소요되는 문제와 이미지를 확대하였을 때 해상도 가 나빠지는 문제 등을 내포하고 있었다.

그레이디언트는 2가지 종류가 있다.

  • 선형 그레이디언트 (Linear Gradient: goes down/up/left/right/diagonally)
  • 방사형 그레이디언트 (Radial Gradient: defined by their center)

대부분의 브라우저에 벤더프리픽스를 사용하여야 하고 브라우저에 따라 조금씩 문법이 상이하여 다루기가 수월하지 않다. 따라서 그레이디언트를 직접 작성하는 것보다 작성 툴을 이용하는 것이 보편적이다.

<!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 : 트랜지션

트랜지션(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)

#1. transition-property

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에 영향을 주는 프로퍼티는 아래와 같다.

  • width
  • height
  • padding
  • margin
  • border
  • display
  • position
  • overflow
  • top
  • right
  • left
  • bottom
  • font-size
  • font-family
  • float
  • font-weight
  • text-align
  • vertical-align
  • line-height
  • clear
  • white-space

#2. transition-duration

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;
}

#3. transition-timing-function

트랜지션 효과의 변화 흐름, 시간에 따른 변화 속도와 같은 일종의 변화의 리듬을 지정한다.

대부분의 타이밍 함수는 큐빅 베이지어(cubic bezier) 를 정의하는 네 점에 의해 정의되므로 상응하는 함수의 그래프로 제공해서 명시할 수 있다. transition-timing-function 프로퍼티값으로 미리 정해둔 5개의 키워드가 제공된다. 기본값은 ease 이다.

프로퍼티값효과
ease기본값. 느리게 시작하여 점점 빨라졌다가 느려지면서 종료한다.
linear시작부터 종료까지 등속 운동을 한다
ease-in느리게 시작한 수 일정한 속도에 다다르면 그 상태로 등속 운동한다.
ease-out일정한 속도의 등속으로 시작해서 점점 느려지면서 종료한다.
ease-in-outease와 비슷하게 느리게 시작하여 느려지면서 종료한다.

<!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>

#4. transition-delay

프로퍼티가 변화한 시점과 트랜지션이 실제로 시작하는 사이에 대기하는 시간초 단위(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>

#5. transition

모든 트랜지션 프로퍼티를 한번에 지정할 수 있는 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 : 애니메이션

애니메이션(Animation) 효과는 HTML 요소에 적용되는 CSS 스타일을 다른 CSS 스타일로 부드럽게 변화시킨다.

애니메이션은 애니메이션을 나타내는 CSS 스타일과 애니메이션의 sequence를 나타내는 복수의 키프레임(@keyframes) 들로 이루어진다. transition 으로도 어느 정도의 애니메이션 효과를 표현할 수 있으나 animation 보다는 제한적이다.

일반적으로 CSS 애니메이션을 사용하면 기존의 JavaScript 기반 애니메이션 실행과 비교하여 더 나은 렌더링 성능 을 제공한다고 알려져 있다. 그러나 경우에 따라서는 JavaScript 를 사용하는 것이 나을 수도 있다. jQuery 등의 애니메이션 기능은 CSS보다 간편하게 애니메이션 효과를 가능케 한다.

  • 비교적 작은 효과나 CSS만으로도 충분한 효과를 볼 수 있는 것은 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)

#1. @keyframes

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; }
}

#2. animation-name

이름을 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>

#3. animation-duration

한 싸이클의 애니메이션에 소요되는 시간초 단위(s) 또는 밀리 초 단위(ms) 로 지정한다.
animation-duration은 반드시 지정해야 한다. 지정하지 않는 경우 기본값 0s가 셋팅되어 어떠한 애니메이션도 실행되지 않는다.

animation-duration: .5s;
animation-duration: 500ms;

#4. animation-timing-function

애니메이션 효과를 위한 수치 함수를 지정한다. 수치 함수는 CSS의 transition효과와 동일하다.

#5. animation-delay

요소가 로드된 시점 과 애니메이션이 실제로 시작하는 사이에 대기하는 시간초 단위(s) 또는 밀리 초 단위(ms) 로 지정한다.

animation-delay: 2s;

#6. animation-iteration-count

애니메이션 주기의 재생 횟수를 지정한다. 기본값은 1이며 infinite로 무한반복 할 수 있다.

animation-iteration-count: 3;

#7. animation-direction

애니메이션이 종료된 이후 반복될 때 진행하는 방향을 지정한다.

프로퍼티값설명
normal기본값으로 from(0%)에서 to(100%) 방향으로 진행한다.
reverseto에서 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>

#8. animation-fill-mode

애니메이션 미실행 시(대기 또는 종료) 요소의 스타일을 지정한다.

프로퍼티값상태설명
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>

#9. animation-play-state

애니메이션 재생 상태(재생 또는 중지)를 지정한다. 기본값은 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>

#10. animation

모든 애니메이션 프로퍼티를 한번에 지정한다. 값을 지정하지 않은 프로퍼티에는 기본값이 지정된다.
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 : 트랜스폼

  • 트랜지션은 CSS 스타일 변경을 부드럽게 표현하기 위해 duration(지속시간)을 부여하여 속도를 조절한다.
  • 애니메이션은 하나의 줄거리(@keyframes)를 구성하여 줄거리 내에서 세부 움직임을 시간 흐름 단위로 제어하여 요소의 움직임을 표현한다.

트랜스폼(Transform)은 요소에 이동(translate) 회전(rotate) 확대축소(scale) 비틀기(skew) 효과를 부여하기 위한 함수를 제공한다. 단 애니메이션 효과를 제공하지는 않기 때문에 정의된 프로퍼티가 바로 적용되어 화면에 표시된다.

트랜스폼은 애니메이션 효과를 위해 사용하여야 하는 것은 아니지만 애니메이션 효과를 부여할 필요가 있다면 트랜지션이나 애니메이션과 함께 사용한다.

#1. 2D 트랜스폼 (2D Transform)

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)

#1.1 transform

변환함수를 프로퍼티값으로 쉼표없이 나열한다. 나열순서에 따라 차례대로 효과가 적용된다.

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>

#1.2 transform-origin

요소의 기본기준점을 설정할 때 사용된다. 기본기준점은 요소의 정중앙이다.(50%,50%)

  • 이동은 기준점을 변경하여도 일정 거리만큼 이동하므로 의미가 없다.
  • 설정값으로 % px top left bottom right 을 사용할 수 있다.
  • 0, 0top 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>

#2. 3D 트랜스폼 (3D Transform)

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)

ㅤㅤ

📍 Web Font : 웹디자인 타이포그래피

웹디자인 관점에서 폰트의 선택 은 중요한 의미를 갖는다. 대부분의 정보는 텍스트와 이미지로 전달되고 아직은 텍스트가 주 를 이루기 때문에 더욱 그러하다. 이전에는 웹에서 사용할 수 있는 아름다운 한글 폰트가 적어 포토샵 등으로 로컬 폰트를 사용하여 텍스트를 이미지로 만들어 사용하였다. 이것은 많은 트래픽을 유발 하고 웹크롤러가 정보를 수집할 수 없어 SEO관점에서도 바람직하지 않다.

웹페이지는 불특정 사용자 를 위해 제작되기 때문에 어떤 디바이스어떤 OS 를 사용하는 사용자가 웹페이지에 접근할 지 알 수 없다. 웹페이지를 구성하는 HTML CSS JavaScript 파일이 사용자의 요청에 의해 서버에서 클라이언트로 다운로드되어 실행되는 것과 같이 폰트 또한 서버에서 클라이언트로 다운로드되어 실행 될 수 있다면 이 문제는 해결될 수 있다.

이러한 문제를 해결할 수 있는 방법이 바로 웹폰트이다. 웹폰트는 사용자가 웹페이지를 요청한 순간 CSS에 기술된 필요 폰트가 서버에서 클라이언트로 전송 된다. 좀 더 구체적으로 말하면 매번 다운로드되는 것은 아니고 클라이언트에 해당 폰트가 존재하지 않을 경우 전송된다.

#1. CDN(Content Delivery Network) 링크 방식

웹폰트를 사용하는 방법 중 가장 간단한 방법은 CDN 링크 를 사용하는 것이다. 아래는 구글에서 제공하는 웹폰트를 사용하는 방법이다.

  • Google Font 에서 사용하고자 하는 웹폰트를 선택한다.
  • 사용하고자하는 폰트를 아래 구문을 CSS 파일에 추가한다.
@import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css);

* { font-family: 'Nanum Gothic', sans-serif; }

@import rule의 url 함수는 서버에서 혹은 지정된 url에서 파일을 찾아 다운로드한다.

#2. 서버 폰트 로딩 방식

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;

ㅤㅤ

📍 Layout : 레이아웃

웹 페이지는 stylelayout 을 담당하는 CSS를 사용하여 layout을 구성하는 것이 바람직하다.

블록 레벨 요소들을 원하는 위치에 배열 레이아웃
https://poiemaweb.com/img/layout-samples.png

화면의 크기에 따라 적절히 화면 구성을 변화시키는 반응형 웹 디자인(Responsive Web Design)
https://poiemaweb.com/img/responsive-web-design-samples.png

CSS를 사용하여 layout을 구성할 때에 자주 사용되는 핵심 기술은 float 이다. layout이란 웹사이트를 구성하는 요소들을 배치할 공간을 분할하고 정렬 하는 것이다. 공간을 분할할 때는 먼저 행을 구분한 후, 행 내부 요소를 분리하는 것이 일반적이다.

#1. Header & Navigation Bar

대부분의 웹사이트는 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 로 지정하고, 상하 margin12px 씩 부여하면 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>

#2. Section & Aside

콘텐츠의 영역을 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;
}

#3. footer

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;
}


이처럼 레이아웃을 구분하고 스타일을 적용하여 간단한 웹의 구성을 제작 할 수 있다.


ㅤㅤ

📍 Responsive Web Design : 반응형 레이아웃

#1. Responsive Web Design 개요

사용자가 어떤 디바이스 로 웹사이트를 방문할 지 알 수 없다. layout 은 방문자의 화면 해상도를 고려 하여야 한다. 가로폭이 너무 큰 layout을 작성하면 작은 해상도 모니터로 방문하였을 때 가로 스크롤이 생겨서 사용이 불편할 수도 있다. 또한 스마트폰이나 태블릿 등 모바일 기기는 화면이 작기 때문에 가독성에 더욱 신경써야 한다.

보통 웹사이트가 축소되어 가로 스크롤 없이 콘텐츠를 볼 수 있으나 글자가 너무 작아지기 때문이다. 데스크탑용 테블릿용 모바일용 웹사이트를 별도 구축할 수도 있지만 One Source Multi Use의 관점에서 올바른 해결책은 아니다. 이러한 문제를 해결하는 방법 중의 하나가 반응형 웹디자인(Responsive Web Design) 이다. 화면 해상도 에 따라 가로폭 이나 배치 를 변경하여 가독성을 높이는 것 이다.

즉, 하나의 웹사이트를 구축하여 다양한 디바이스의 화면 해상도에 최적화된 웹사이트를 제공하는 것이다.

#1.1 viewport meta tag

viewport란 웹페이지의 가시영역을 의미한다. viewport는 디바이스에 따라 차이가 있다.

예를 들어 모바일 브라우저는 주화면이 세로 화면 이고 윈도우 resize가 불가 하며 화면 터치를 사용 하는 등 데스크탑 브라우저와 구성이나 형태가 다르다.또한 모바일의 화면은 데스크탑 화면보다 훨씬 작으므로 데스크탑용 웹페이지를 그대로 모바일에 출력하면 가독성이 현저히 나빠진다. 따라서 viewport 를 이용하여 디바이스의 특성과 디바이스의 화면 크기 등을 고려하여 각종 디바이스 사용자에게 최적화된 웹페이지를 제공할 수 있다.

  • meta tag는 브라우저 혹은 검색엔진최적화(SEO)를 위해 검색엔진에게 메타데이터를 전달하기 위해 사용된다.
  • viewport meta tag는 브라우저의 화면 설정과 관련된 정보를 제공한다.
프로퍼티Description사용예
widthviewport 너비(px). 기본값: 980pxwidth=240
width=device-width
heightviewport 높이(px)height=800
width=device-height
initial-scaleviewport초기 배율initial-scale=1.0
user-scale확대 축소 가능 여부user-scale=no
maximum-scaleviewport 최대 배율maximum-scale=2.0
minimum-scaleviewport 최소 배율minimum-scale=1.0

meta tag 에서는 px단위 를 사용하며 단위 표현은 생략한다. 복수개의 프로퍼티를 사용할 때는 쉼표(,) 로 구분한다. 일반적으로 viewport meta tag는 모바일 디바이스에서만 적용된다.

<meta name="viewport" content="width=device-width, initial-scale=1.0">

가장 일반적인 viewport 설정이다. 가로폭을 디바이스의 가로폭에 맞추고 초기 화면 배율을 100%로 설정하는 것을 의미한다.

#1.2 @media

@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 Query의 문법
@media not|only mediatype and (expressions) {
  CSS-Code;
}
@media screen and (min-width: 480px) {
  body {
    background-color: lightgreen;
  }
}
  • Media Query의 표현식에서 사용할 수 있는 프로퍼티
프로퍼티Description
widthviewport 너비(px)
heightviewport 높이(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)xs576px 미만스마트폰 세로
작은(Small)sm576px 이상스마트폰 가로
중간(Medium)md768px 이상타블렛
큰(Large)lg992px 이상데스크탑
아주 큰(Extra large)xl1200px 이상큰 데스크탑
/* 큰 데스크탑 */

@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) {
/* 데스크탑 */
}

#2. Responsive Navigation Bar

레이아웃의 구조를 위해 제작한 웹을 반응형 웹으로 수정 할 수 있다.

3-1. 디바이스 해상도 에 따라 반응할 수 있도록 viewport meta tagmedia 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 방식은 해상도가 큰 순서로 기술한다.

#2.1 Responsive Navigation Bar - Tablet

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;
  }
}

#2.2 Responsive Navigation Bar - Smartphone

태블릿 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 tagfor 프로퍼티값과 input tagid 프로퍼티값이 일치하여야 한다.

<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>

#3. Section & Aside & Footer

현재 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 : 플렉스 박스 레이아웃

#1. Introduction

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의 장점

  • 1줄의 코드 추가로 수평 정렬이 가능하다.
  • 요소의 상하좌우 정렬, 순서 변경이 간단하다.
  • 요소가 간격 조절이 간단하다.
  • 서로 다른 height를 갖는 요소의 수평정렬 시, 간단히 상하중앙 정렬이 가능하다.

#2. Usage

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 이 된다.

#3. Flexbox container 속성

#3.1 flex-direction

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;
}

#3.2 flex-wrap

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;
}

#3.3 flex-flow

flex-flow 속성은 flex-direction 속성과 flex-wrap 속성을 설정하기 위한 shorthand이다. 기본값은 row nowrap 이다.

.flex-container {
  flex-flow: <flex-direction> || <flex-wrap>;
}

#3.4 justify-content

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;
}

#3.5 align-items

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;
}

#3.6 align-content

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;
}

#4. Flexbox item 속성

float clear vertical-align 속성은 flex item에 영향을 주지 않는다.

#4.1 order

flex item의 배치 순서를 지정 한다. HTML 코드를 변경하지 않고 order 속성값을 지정하는 것으로 간단히 재배치할 수 있다.

기본 배치 순서는 flex container에 추가된 순서이다. 기본값은 0 이다.

.flex-item {
  order: 정수값;
}

#4.2 flex-grow

flex item의 너비에 대한 확대 인자(flex grow factor)를 지정한다. 기본값은 0 이고 음수값은 무효 하다.

.flex-item {
  flex-grow: 양의 정수값;
}

모든 flex item이 동일한 flex-grow 속성값을 가지면 모든 flex item은 동일한 너비를 갖는다.

두번째 flex item의 flex-grow 속성값을 3으로 지정하면 다른 flex item보다 더 넓은 너비를 갖는다.

#4.3 flex-shrink

flex item의 너비에 대한 축소 인자(flex shrink factor)를 지정한다. 기본값은 1 이고 음수값은 무효 하다. 0 을 지정하면 축소가 해제되어 원래의 너비를 유지 한다.

기본적으로 모든 flex item은 축소된 상태로 지정(기본값 1)하고 두번째 flex item만 축소를 해제(flex-shrink: 0;)하면 원래의 너비를 유지한다.

.flex-item {
  flex-shrink: 양의 정수값;
}

#4.4 flex-basis

flex item의 너비 기본값px % 등의 단위로 지정한다. 기본값은 auto 이다.

.flex-item {
  flex-basis: auto | <width>;
}

#4.5 flex

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
}

#4.6 align-self

align-items 속성보다 우선하여 개별 flex item을 정렬한다. 기본값은 auto 이다.

.flex-item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

3번째, 4번째 flex item은 align-self 속성값이 우선 적용되어 정렬된다.

#5. Flexbox playground

https://codepen.io/enxaneta/pen/adLPwv


ㅤㅤ

📍 Horizontal & Vertical Centering : 수평/수직 중앙 정렬

#1. 수평 정렬(Horizontal Align)

#1.1 inline/inline-block 요소

정렬 대상 요소의 부모 요소에 text-align: center;를 지정한다.

.container {
  text-align: center;
}

#1.2 block 요소

정렬 대상 요소에 너비를 명시적으로 지정 하고 margin-rightmargin-left 프로퍼티에 auto 를 지정한다. 정렬 대상 요소에 너비를 명시적으로 지정하지 않으면 너비는 full width 가 되므로 중앙 정렬이 필요없다.

.item {
  width: 200px;
  margin: 20px auto;
}

#1.3 복수의 block 요소

복수의 block 요소는 기본적으로 수직 정렬된다.
수평정렬 하기 위해서는 정렬 대상 block 요소inline-block 요소로 변경한 후 부모 요소에 text-align: center;를 지정한다.
정렬 대상 요소width 를 지정하지 않으면 콘텐츠에 너비에 맞추어 너비가 결정되므로 명시적으로 너비를 지정한다.

.container {
  text-align: center;
}
.item {
  width: 150px;
  display: inline-block;
}

#1.4 Flexbox

flexbox 를 사용할 수도 있다. 정렬 대상의 부모 요소 에 선언한다.

.flex-center {
  display: flex;
  justify-content: center;
}

Result

#2. 수직 정렬(Vertical Align)

#2.1 inline/inline-block 요소

#2.1.1 Single line

정렬 대상의 부모 요소에 padding-toppadding-bottom 프로퍼티값을 동일하게 적용한다.

.container {
  padding: 50px;
}

padding 을 사용할 수 없는 경우, 요소의 heightline-height 프로퍼티값을 동일하게 적용 한다. 단 이 방법은 행간이 지나치게 넓어지거나 Click Dead Zone 이슈 가 발생하는 등 여러 줄의 텍스트 에는 사용할 수 없다.

.container {
  height: 100px;
  line-height: 100px;
}

#2.1.2 Multiple lines

여러 줄의 텍스트의 경우, padding-toppadding-bottom 프로퍼티값을 동일하게 적용하는 방법도 가능하다.
또 다른 방법으로 vertical-align 프로퍼티를 사용한 방법도 가능하다. 이 방법은 table 속성을 사용하여야 한다.

.parent {
  display: table;
  height: 100px;
}
.child {
  display: table-cell;
  vertical-align: middle;
}

#2.1.3 Flexbox

vertical-align 프로퍼티를 사용하는 방법은 table 프로퍼티를 사용하여야 하므로 번거로울 수 있다. 좀 더 간단한 방법은 flexbox를 사용하는 것이다.

.container {
  display: flex;
  justify-content: center;
  flex-direction: column;
  height: 400px;
}

#2.2 block 요소

#2.2.1 요소의 높이가 고정되어 있는 경우

부모 요소를 기준으로 절대 위치 를 지정한다.

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  height: 100px;
  /*요소의 높이(100px)의 반 만큼 위로 이동*/
  margin-top: -50px;
}

#2.2.2 요소의 높이가 불확정 상태의 경우

부모 요소를 기준으로 절대 위치 를 지정한다.

.parent {
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  /*요소의 높이의 반(50%) 만큼 위로 이동*/
  transform: translateY(-50%);
}

#2.2.3 Flexbox

부모 요소에 Flexbox layout 을 지정한다.

.parent {
  display: flex;
  /*위에서 아래로 수직 배치*/
  flex-direction: column;
  /*중앙정렬*/
  justify-content: center;
}

Result

#3. 수평/수직 정렬(Horizontal & Vertical Align)

요소의 너비와 높이가 고정되어 있는 경우, 요소의 너비와 높이가 불확정 상태의 경우 모두 사용 가능한 방법이다

.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;
}

Result


ㅤㅤ

📍 Typography : image 요소 아래에 패딩 된 여분의 공간 제거하기

<!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] 를 정독하며 정리한 글입니다.

출처 : 웹 프로그래밍 튜토리얼 | PoiemaWeb

profile
https://kyledev.tistory.com/

0개의 댓글