본문 바로가기
학원에서 배운 것/JavaScript

지금까지 배운 것을 바탕으로 To do List 구현

by 쿠리의일상 2023. 2. 16.

지금까진 강사님이 주신 레퍼런스를 바탕으로 JS 기능을 구현했었는데, 이번 기회에 시간을 내서 HTML과 CSS, JS까지 모두 혼자 구현해보기로 하였다. 부트스트랩을 쓰는게 훨씬 예쁘기는 하겠다만 ... 디자인을 최대한 노력해보며(?)

사실 색 지정이 제일 어려웠다.

 

이렇게 무식하게 하다보면 언젠가 실력이 늘겠지!

 

1. HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>오늘 할 일</title>
  <!-- Reset CSS -->
  <link href="https://cdn.jsdelivr.net/npm/reset-css@5.0.1/reset.min.css" rel="stylesheet">
  <!-- main CSS -->
  <link rel="stylesheet" href="./todo-list.css"/>
  <!-- main JS -->
  <script defer src="./todo-list.js"></script>
</head>
<body>
  <section>
    <div class="inner">
      <div class="todo-list">
        <h1>To Do List</h1>
        <hr/>
        <div class="todo-input">
          <input type="text" placeholder="할일을 추가해주세요"/>
          <button class="btn btn--send">추가</button>
        </div>
        <ul class="todo-contents">
        </ul>
      </div>
    </div>
  </section>
</body>
</html>

순수 HTML

header를 굳이 나눌 필요는 없어보여서 한 section으로 만들고자 했다.

간단하게

  1. 제목 부분
  2. 입력 받는 부분
  3. 리스트가 추가되는 부분

이렇게 3부분으로 나눠줬다.

 

 

여기에 CSS를 입혀준다.

2. CSS

section {
  width: 100vw;
}
section .inner {
  box-sizing: border-box;
  margin: auto;
  padding: 120px;
}
.btn {
  padding: 5px 13px;
  border-radius: 5px;
  font-size: 1rem;
  margin-left: 10px;
  transition: 0.6s;
}
.btn--send {
  padding: 12px 15px;
  background-color: rgb(187, 231, 255);
  border-color: rgb(187, 231, 255);
  color : rgb(49, 137, 188);
}
.btn--send:hover, 
.btn--delete:hover {
  color : black;
  background-color: white;
  border-color:#ccc;
  box-shadow: 5px 5px 0px #6a6a6a;
}
.btn--delete {
  background-color: rgb(255, 247, 175);
  border-color: rgb(255, 247, 175);
  color : rgb(178, 164, 35);
}

section .inner .todo-list {
  width: 100%;
  border : 1px solid rgb(130, 123, 47);
  box-shadow: 2px 2px 4px #858585;
}

section .inner .todo-list > h1 {
  position: relative; 
  font-size: 3rem;
  font-weight: 700;
  text-align: center;
  margin: 50px;
}

section .inner .todo-list > h1:after,
section .inner .todo-list > h1::before {
  content: '[';
  display: inline-block;
  position: relative;
  top: 1px;
  height: 100%;
  font-size: 1.25em;
  color: rgb(49, 137, 188);
  
  transition: all 0.7s ease;
}
section .inner .todo-list > h1:after {
  content: ']'; 
}
section .inner .todo-list > h1:hover:before {
  transform: translateX(-15px);
  opacity: 0;
}
section .inner .todo-list > h1:hover:after {
  transform: translateX(15px);
  opacity: 0;
}

section .inner .todo-list > hr {
  border: 0;
  height: 1px;
  background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0));
  transition: .7s;
}
section .inner .todo-list > hr:hover {
  background-image: linear-gradient(to right, rgba(41, 87, 255, 0), rgba(41, 87, 255, 0.75), rgba(41, 87, 255, 0));
}

section .inner .todo-list .todo-input {
  text-align: center;
  margin: 20px 0;
}
section .inner .todo-list .todo-input > input {
  border-radius: 3px;
  padding: 8px 7px 8px 7px;
  font-size: 1rem;
  border-color: rgb(255, 247, 175);
  transition: 0.5s;
  color : #959595;
  transform: translateY(3px);
}
section .inner .todo-list .todo-input > input:focus {
  background-color: rgb(240, 240, 240);
  outline: none;
  border-color: rgb(49, 137, 188);
  color: black;
  font-size: 1.2rem;
  
}
section .inner .todo-list .todo-input > .btn--send {}

section .inner .todo-list .todo-contents {

  margin-bottom: 50px;
}
section .inner .todo-list .todo-contents > li {
  width: 80%;
  height: 48px;
  line-height: 51px;
  margin: 0 auto;
  margin-bottom: 15px;
  padding-left: 15px;
  background-color:rgb(228, 245, 255);
  position: relative;
}
section .inner .todo-list .todo-contents > li > input {
  width: 17px;
  height: 17px;
  margin-right: 8px;
  transform: translateY(3px);
}

section .inner .todo-list .todo-contents > li > button.btn--delete {
  position: absolute;
  right: 15px;
  bottom: 7px;
  transform: translateY(-1px);
}

트랜지션 효과는 h1과 버튼, 인풋필드에만 주었다.

 

 

3. JS

const inputField = document.querySelector('.todo-input > input');
const sendBtn = document.querySelector('.btn.btn--send');
const todoList = document.querySelector('.todo-contents');

let addItem = function() {
  if(inputField.value === "") {
    inputField.setAttribute('placeholder', '내용을 입력해주세요!');
    return;
  }

  const itemLi = document.createElement('li');
  const liCheckBox = document.createElement('input');
  const textSpan = document.createElement('span');
  const liDeleteButton = document.createElement('button');

  // 텍스트 부분
  textSpan.textContent = inputField.value;

  // 체크박스
  liCheckBox.type = 'checkbox';
  liCheckBox.addEventListener('click', function(e) {
    if(liCheckBox.checked === true) {
      textSpan.style.textDecoration = 'line-through';
    } else {
      textSpan.style.textDecoration = 'none';
    }
  });

  // 삭제 버튼
  liDeleteButton.innerText = "삭제";
  liDeleteButton.addEventListener('click', function(e) {
    e.target.parentNode.remove();
  });
  liDeleteButton.classList.add('btn');
  liDeleteButton.classList.add('btn--delete');

  // li에 아이템 추가
  itemLi.appendChild(liCheckBox);
  itemLi.appendChild(textSpan);
  itemLi.appendChild(liDeleteButton);

  // ul에 최종 추가
  todoList.appendChild(itemLi);

  inputField.value = "";
  inputField.focus();
};

sendBtn.addEventListener('click', addItem);

자바스크립트 기능은

  1. 추가 버튼을 누르면 인풋필드의 value를 li 내 span에 넣어주고
  2. li 태그와 그 안의 체크박스, span, 삭제 버튼을 만들고
  3. ul 태그 아래에 li 태그를 넣어주기
  4. 삭제 버튼의 경우 이벤트 객체를 활용하여 remove() 시키기
  5. 체크박스의 경우 span의 스타일을 line-through 해주기

 

 

투두 리스트를 만들어보니 어렵기는 했지만 재미있었다 🥳