본문 바로가기
JavaScript

[JavaScript] Sidebar 만들기

by teamnova 2024. 4. 10.
728x90

 

오늘은 Sidebar를 만들어보겠습니다. 

 

 

 

css파일에서의 중요한 부분은 3곳입니다.

1.  .sidbar {}   : 사이드 바의 기본 스타일 설정 

2. .show-sidebar{} : 사이드바 숨김 

3. @media screen and (min-width: 676px) {} : 반응형 사이드바  

 

js파일에서 중요한 부분은 2개입니다. 

1. sidebar.classList.toggle("className") : sidebar 요소의 클래스 목록에 접근하여  지정된 클래스가 있으면 제거하고, 없으면 추가합니다

2. sidebar.classList.remove("className") : sidebar 요소의 클래스 목록에 접근하여 지정된 클래스를 제거합니다.

 

 

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Sidebar</title>
    <!-- font-awesome -->
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css"
    />

    <!-- styles -->
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <button class="sidebar-toggle">
      <i class="fas fa-bars"></i>
    </button>
    <aside class="sidebar">
      <div class="sidebar-header">
        <img src="logo.svg" class="logo" alt="" />
        <button class="close-btn"><i class="fas fa-times"></i></button>
      </div>
      <!-- links -->
      <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>
      <!-- social media -->
      <ul class="social-icons">
        <li>
          <a href="https://www.twitter.com">
            <i class="fab fa-facebook"></i>
          </a>
        </li>
        <li>
          <a href="https://www.twitter.com">
            <i class="fab fa-twitter"></i>
          </a>
        </li>
        <li>
          <a href="https://www.twitter.com">
            <i class="fab fa-behance"></i>
          </a>
        </li>
        <li>
          <a href="https://www.twitter.com">
            <i class="fab fa-linkedin"></i>
          </a>
        </li>
        <li>
          <a href="https://www.twitter.com">
            <i class="fab fa-sketch"></i>
          </a>
        </li>
      </ul>
    </aside>
    <!-- javascript -->
    <script src="app.js"></script>
  </body>
</html>

 

 

app.js

// ".sidebar-toggle" 클래스를 가진 요소를 찾아 toggleBtn 변수에 할당합니다.
const toggleBtn = document.querySelector(".sidebar-toggle");
// ".close-btn" 클래스를 가진 요소를 찾아 closeBtn 변수에 할당합니다.
const closeBtn = document.querySelector(".close-btn");
// ".sidebar" 클래스를 가진 요소를 찾아 sidebar 변수에 할당합니다.
const sidebar = document.querySelector(".sidebar");

// 토글 버튼에 클릭 이벤트 리스너를 추가합니다.
toggleBtn.addEventListener("click", function () {
  // 클릭 시, sidebar 요소의 클래스 리스트에 "show-sidebar" 클래스를 토글합니다.
  // 즉, "show-sidebar" 클래스가 있으면 제거하고, 없으면 추가합니다.
  sidebar.classList.toggle("show-sidebar");
});

// 닫기 버튼에 클릭 이벤트 리스너를 추가합니다.
closeBtn.addEventListener("click", function () {
  // 클릭 시, sidebar 요소의 클래스 리스트에서 "show-sidebar" 클래스를 제거합니다.
  sidebar.classList.remove("show-sidebar");
});

 

styles.css

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

/*
=============== 
Variables
===============
*/

: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;
}
/*
=============== 
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;
  }
}
/*  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;
}

/*
=============== 
Sidebar
===============
*/
.sidebar-toggle {
  position: fixed;
  top: 2rem;
  right: 3rem;
  font-size: 2rem;
  background: transparent;
  border-color: transparent;
  color: var(--clr-primary-5);
  transition: var(--transition);
  cursor: pointer;
  animation: bounce 2s ease-in-out infinite;
}
.sidebar-toggle:hover {
  color: var(--clr-primary-7);
}
@keyframes bounce {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1);
  }
}

.sidebar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 1.5rem;
}
.close-btn {
  font-size: 1.75rem;
  background: transparent;
  border-color: transparent;
  color: var(--clr-primary-5);
  transition: var(--transition);
  cursor: pointer;
  color: var(--clr-red-dark);
}
.close-btn:hover {
  color: var(--clr-red-light);
  transform: rotate(360deg);
}
.logo {
  justify-self: center;
  height: 40px;
}

.links a {
  display: block;
  font-size: 1.5rem;
  text-transform: capitalize;
  padding: 1rem 1.5rem;
  color: var(--clr-grey-5);
  transition: var(--transition);
}
.links a:hover {
  background: var(--clr-primary-8);
  color: var(--clr-primary-5);
  padding-left: 1.75rem;
}
.social-icons {
  justify-self: center;
  display: flex;
  padding-bottom: 2rem;
}
.social-icons a {
  font-size: 1.5rem;
  margin: 0 0.5rem;
  color: var(--clr-primary-5);
  transition: var(--transition);
}
.social-icons a:hover {
  color: var(--clr-primary-1);
}

.sidebar {
  position: fixed; /* 사이드바를 뷰포트에 고정시키며, 스크롤 시에도 같은 위치에 유지 */
  top: 0; /* 뷰포트의 맨 위에서 시작 */
  left: 0; /* 뷰포트의 왼쪽에서 시작 */
  width: 100%; /* 사이드바의 너비를 뷰포트의 전체 너비로 설정 */
  height: 100%; /* 사이드바의 높이를 뷰포트의 전체 높이로 설정 */
  background: var(--clr-white); /* 사이드바의 배경색 설정 */
  display: grid; /* CSS 그리드 레이아웃 사용 */
  grid-template-rows: auto 1fr auto; /* 그리드 행의 크기를 상단과 하단에 자동, 중간에는 나머지 공간을 차지하도록 설정 */
  row-gap: 1rem; /* 행 사이의 간격을 1rem으로 설정 */
  box-shadow: var(--clr-red-dark); /* 사이드바의 그림자 색상 설정 */
  transition: var(--transition); /* 변화(여기서는 위치 변경)에 대한 애니메이션 효과를 부드럽게 전환 */
  transform: translate(-100%); /* 사이드바를 왼쪽으로 100% 이동시켜 뷰포트 밖으로 숨김 */
}
.show-sidebar {
  transform: translate(0); /* 사이드바를 원래 위치로 이동시켜 화면에 표시 */
}

/* 미디어 쿼리: 스크린에서 뷰포트 너비가 676픽셀 이상일 경우 적용 */
@media screen and (min-width: 676px) {
  .sidebar {
    width: 400px;  /* 사이드바 너비를 400픽셀로 설정 */
  }
}

 

 

결과 

 

오른쪽 상단의 햄버거 메뉴를 눌러 사이드바 동작을 확인하세요.