지금까진 강사님이 주신 레퍼런스를 바탕으로 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>
header를 굳이 나눌 필요는 없어보여서 한 section으로 만들고자 했다.
간단하게
- 제목 부분
- 입력 받는 부분
- 리스트가 추가되는 부분
이렇게 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);
자바스크립트 기능은
- 추가 버튼을 누르면 인풋필드의 value를 li 내 span에 넣어주고
- li 태그와 그 안의 체크박스, span, 삭제 버튼을 만들고
- ul 태그 아래에 li 태그를 넣어주기
- 삭제 버튼의 경우 이벤트 객체를 활용하여 remove() 시키기
- 체크박스의 경우 span의 스타일을 line-through 해주기
투두 리스트를 만들어보니 어렵기는 했지만 재미있었다 🥳
'학원에서 배운 것 > JavaScript' 카테고리의 다른 글
KDT 5th 웹개발자 입문 수업 17일차 (0) | 2023.02.17 |
---|---|
KDT 5th 웹개발자 입문 수업 16일차 (0) | 2023.02.16 |
KDT 5th 웹개발자 입문 수업 15일차 (0) | 2023.02.15 |
KDT 5th 웹개발자 입문 수업 14일차 (0) | 2023.02.14 |
KDT 5th 웹개발자 입문 수업 13일차 (0) | 2023.02.13 |