[JavaScript] 반응형 내비게이션 바 제작

폰트

@import url("https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap");

@import : 외부 스타일 시트를 현재 스타일 시트로 가져오는 데 사용, url() 내에는 가져올 외부 파일의 경로가 포함

변수 정의

:root {
  /* dark shades of primary color*/
  --clr-primary-1: hsl(205, 86%, 17%);
  --clr-primary-2: hsl(205, 77%, 27%);
  --clr-primary-3: hsl(205, 72%, 37%);
  --clr-primary-4: hsl(205, 63%, 48%);
  
  /* primary/main color */
  --clr-primary-5: hsl(205, 78%, 60%);
  
  /* lighter shades of primary color */
  --clr-primary-6: hsl(205, 89%, 70%);
  --clr-primary-7: hsl(205, 90%, 76%);
  --clr-primary-8: hsl(205, 86%, 81%);
  --clr-primary-9: hsl(205, 90%, 88%);
  --clr-primary-10: hsl(205, 100%, 96%);
  
  /* darkest grey - used for headings */
  --clr-grey-1: hsl(209, 61%, 16%);
  --clr-grey-2: hsl(211, 39%, 23%);
  --clr-grey-3: hsl(209, 34%, 30%);
  --clr-grey-4: hsl(209, 28%, 39%);
  
  /* grey used for paragraphs */
  --clr-grey-5: hsl(210, 22%, 49%);
  --clr-grey-6: hsl(209, 23%, 60%);
  --clr-grey-7: hsl(211, 27%, 70%);
  --clr-grey-8: hsl(210, 31%, 80%);
  --clr-grey-9: hsl(212, 33%, 89%);
  --clr-grey-10: hsl(210, 36%, 96%);
  --clr-white: #fff;
  --clr-red-dark: hsl(360, 67%, 44%);
  --clr-red-light: hsl(360, 71%, 66%);
  --clr-green-dark: hsl(125, 67%, 44%);
  --clr-green-light: hsl(125, 71%, 66%);
  --clr-black: #222;
  --ff-primary: "Roboto", sans-serif;
  --ff-secondary: "Open Sans", sans-serif;
  --transition: all 0.3s linear;
  --spacing: 0.1rem;
  --radius: 0.25rem;
  --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
  --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
  --max-width: 1170px;
  --fixed-width: 620px;
}

:root 문서의 최상위 요소 나타냄, 전역 CSS 선언할 때 유용하게 사용

전역 스타일 정의

/*
=============== 
Global Styles
===============
*/

*,
::after,
::before {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: var(--ff-secondary);
  background: var(--clr-grey-10);
  color: var(--clr-grey-1);
  line-height: 1.5;
  font-size: 0.875rem;
}

ul {
  list-style-type: none;
}

a {
  text-decoration: none;
}

h1,
h2,
h3,
h4 {
  letter-spacing: var(--spacing);
  text-transform: capitalize;
  line-height: 1.25;
  margin-bottom: 0.75rem;
  font-family: var(--ff-primary);
}

h1 {
  font-size: 3rem;
}
h2 {
  font-size: 2rem;
}
h3 {
  font-size: 1.25rem;
}
h4 {
  font-size: 0.875rem;
}
p {
  margin-bottom: 1.25rem;
  color: var(--clr-grey-5);
}

@media screen and (min-width: 800px) {
  h1 {
    font-size: 4rem;
  }
  h2 {
    font-size: 2.5rem;
  }
  h3 {
    font-size: 1.75rem;
  }
  h4 {
    font-size: 1rem;
  }
  body {
    font-size: 1rem;
  }
  h1,
  h2,
  h3,
  h4 {
    line-height: 1;
  }
}

가상요소?

선택자에 추가하는 키워드로, 존재하지 않는 요소를 존재하는 것처럼 부여하여 문서의 특정 부분 선택 가능
::before,::after : CSS의 가상 요소로, 선택한 요소의 내용의 앞, 뒤에 생성된 요소로 실제 HTML에는 존재하지 않지만 CSS 사용해 내용 추가할 수 있음

css 초기화 기술

::after,
::before {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

이 코드에서 가상요소를 사용해 작성했던 코드를 말할 수 있겠다.
* 모든 요소와 ::after 그 이후, ::before 그 이전
일괄적으로 기본의 스타일을 적용해 주로 브라우저 간의 기본 스타일 차이를 제거하고 일관된 레이아웃을 구축하기 위해 사용됨.

미디어 쿼리

뷰포트의 크기에 따라 서로 다른 레이아웃을 생성할 수 있게 함

@media screen and (min-width: 800px) {
  h1 {
    font-size: 4rem;
  }
  h2 {
    font-size: 2.5rem;
  }
  h3 {
    font-size: 1.75rem;
  }
  h4 {
    font-size: 1rem;
  }
  body {
    font-size: 1rem;
  }
  h1,
  h2,
  h3,
  h4 {
    line-height: 1;
  }
}

즉 이 코드에서는, screen의 최소너비(min-width) 800px일때 실행하도록 하고있다.
-> 창을 키우면 보일 화면

전역 클래스 정의

/*  global classes */

/* section */
.section {
  padding: 5rem 0;
}

.section-center {
  width: 90vw;
  margin: 0 auto;
  max-width: 1170px;
}

@media screen and (min-width: 992px) {
  .section-center {
    width: 95vw;
  }
}

main {
  min-height: 100vh;
  display: grid;
  place-items: center;
}

네비게이션 바

nav {
  background: var(--clr-white);
  box-shadow: var(--light-shadow);
}

.nav-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem;
}

.nav-toggle {
  font-size: 1.5rem;
  color: var(--clr-primary-5);
  background: transparent;
  border-color: transparent;
  transition: var(--transition);
  cursor: pointer;
}

.nav-toggle:hover {
  color: var(--clr-primary-1);
  transform: rotate(90deg);
}

.logo {
  height: 40px;
}

.links a {
  color: var(--clr-grey-3);
  font-size: 1rem;
  text-transform: capitalize;
  letter-spacing: var(--spacing);
  display: block;
  padding: 0.5rem 1rem;
  transition: var(--transition);
}

.links a:hover {
  background: var(--clr-primary-8);
  color: var(--clr-primary-5);
  padding-left: 1.5rem;
}

.social-icons {
  display: none;
}

.links {
  height: 0;
  overflow: hidden;
  transition: var(--transition);
}

.show-links {
  height: 10rem;
}

@media screen and (min-width: 800px) {
  .nav-center {
    max-width: 1170px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem;
  }
  .nav-header {
    padding: 0;
  }
  .nav-toggle {
    display: none;
  }
  .links {
    height: auto;
    display: flex;
  }
  .links a {
    padding: 0;
    margin: 0 0.5rem;
  }
  .links a:hover {
    padding: 0;
    background: transparent;
  }
  .social-icons {
    display: flex;
  }
  .social-icons a {
    margin: 0 0.5rem;
    color: var(--clr-primary-5);
    transition: var(--transition);
  }
  .social-icons a:hover {
    color: var(--clr-primary-7);
  }
}

:hover

마우스 호버(hover)될 때 적용되는 스타일을 지정하는 가상 클래스
호버: 사용자가 마우스를 요소 위에 가져가는 동작

app.js

여기를 채우는 것이 과제였다. 이 전에 습득하여 사용해야했던 함수 3개

1. document.querySelector(선택자)

제공한 선택자와 일치하는 문서 내 첫번째 요소 반환, 없으면 null 반환

2. 이벤트실행할타겟.addEventListner(이벤트타입, 실행할함수) { ... }

3. classList.toggle()

  • 인수 1개:
    클래스 존재한다면 제거, false 반환
    클래스 존재하지않으면 클래스 추가, true 반환
  • 인수 2개:
    두 번째 인수 true면 클래스 추가
    두 번째 인수 false면 클래스 제거

우선 이렇게 정리한 뒤에는 어떠한 주석에 어떠한 것을 써야할 지 생각하는 것은 쉬웠다.

// navToggle 클래스를 가진 요소를 DOM에서 선택하여 변수에 할당

우선 navToggle 클래스를 가진 요소와 그 클래스를 살펴보자.
index.html

<button class="nav-toggle">
	<i class="fas fa-bars"></i>
</button>

style.css

.nav-toggle {
  font-size: 1.5rem;
  color: var(--clr-primary-5);
  background: transparent;
  border-color: transparent;
  transition: var(--transition);
  cursor: pointer;
}
.nav-toggle:hover {
  color: var(--clr-primary-1);
  transform: rotate(90deg);
}

html에서의 박스 위치와 css의 기능과 스타일을 보았을 때


이 것을 구현하는 부분인 것을 알 수 있다. 그 점을 인지하고 주어진 주석대로 코드를 작성하면
var navToggle = document.querySelector('.nav-toggle');

아까처럼 links 클래스를 가진 요소와 그 클래스를 살펴보면
index.html

<ul class="links">
  <li>
    <a href="index.html">home</a>
  </li>
  <li>
    <a href="about.html">about</a>
  </li>
  <li>
    <a href="projects.html">projects</a>
  </li>
  <li>
     <a href="contact.html">contact</a>
  </li>
</ul>

style.css

.links a {
  color: var(--clr-grey-3);
  font-size: 1rem;
  text-transform: capitalize;
  letter-spacing: var(--spacing);
  display: block;
  padding: 0.5rem 1rem;
  transition: var(--transition);
}
.links a:hover {
  background: var(--clr-primary-8);
  color: var(--clr-primary-5);
  padding-left: 1.5rem;
}
.social-icons {
  display: none;
}
.links {
  height: 0;
  overflow: hidden;
  transition: var(--transition);
}

@media screen and (min-width: 800px) {
  /*...*/
  .links {
    height: auto;
    display: flex;
  }
  .links a {
    padding: 0;
    margin: 0 0.5rem;
  }
  .links a:hover {
    padding: 0;
    background: transparent;
  }
 /*...*/
}

 

html에서의 박스 위치와 css의 기능과 스타일을 보았을 때
이 것을 구현하는 부분인 것을 알 수 있다. 그 점을 인지하고 주어진 주석대로 코드를 작성하면
var links = document.querySelector('.links');

// navToggle 요소에 대한 클릭 이벤트 리스너를 추가합니다.

navToggle.addEventListener('click', function() {});
말 그대로 정리하면 이러한 코드를 작성할 수 있었다.
이는 navToggle 요소, 즉


이것을 클릭했을 때 funciton()의 { }을 실행하는 것이라는 것을 이해할 수 있다.

여기서 생각했을 때,


이 부분, 즉 links 요소를 보여주는 것으로 작성하면 된다는 것을 이해했다.

동시에 그것을 구현하는 것이 바로 이 주석인 것을 이해할 수 있었다.

show-links 클래스를 가진 요소와, 그 클래스를 확인해보자면
style.css

.show-links {
  height: 10rem;
}

그리고 index.html 파일에서는 찾을 수 없는 것을 볼 수 있다. 그렇기에, links 요소의 클래스 목록에 show-links클래스가 없기 때문에 추가하게 한다는 것이다. 그리고 또 한번 버튼을 누르면, show-links클래스가 있기 때문에 제거 된다는 것이다.

그런데 show-links클래스에는 height 밖에 들어있지 않아서 이상함을 느낄 수 있는데,
원래의 link 클래스의 height: 0이라는 것을 보면, 이 클래스가 추가됨으로써 요소가 생기도록 작성되어있다는 것을 알 수 있다.

그리하여 코드를 작성하면

navToggle.addEventListener('click', function() {
  links.classList.toggle('show-links');
});

으로 작성할 수 있다.