HTML , CSS , JS

투 두 리스트 (ToDoList) 페이지 만들기

ilsancityboy 2023. 11. 6. 22:43

이번 글에서는 html , css , js 를 사용하여 투두리스트 페이지를 만들어 볼 것이다.
대략적인 순서는 이렇다.

  1. Html 작성 ( 타이틀 , 할 일을 적어 넣는 필드 , 할일 목록 )
  2. CSS 작성 ( 각 요소들을 보기 좋게 꾸며주기 )
  3. JS 작성 ( 페이지에서 동적 행동이 필요한 요소들을 찾아내고 동작 코드 넣기 )

 

HTML 작성

<!DOCTYPE html>
<head>
	<meta charset="UTF-8">
    
    //PC, 모바일 어디에서 보나 해상도에 맞게끔 보여지게 해줌
	<meta name="viewport" content="width=device-width, initial-scale=1.0"> 
	<title>투두 리스트 페이지</title>
	<link rel="stylesheet" href="styles.css">
</head>
<body>
   <section class="container">
	<!--타이틀부분-->
	<div class="Title-container">
		<img class="Title_img" src='img/title.png' alt="이미지">
		<h1 class="Title">To do List</h1>
	</div>
	

	<!--입력폼 부분-->
	<form class="form">
		<!--사용자 인터페이스 항목의 라벨 정의-->
		<div>
			<label class="form_label" for="todo">오늘 해야할일은~</label>
			<input class="form_input" type="text" id="todo" name="to-do" size="30" required>
			<button class="input_button"><span>입력!</span></button>
		</div>
	</form>
	<!--입력받은 리스트 메모해두는곳-->
	<div>
		<ul class="List">
		</ul>
	</div>
   </section>
  <script src="test.js"></script>
</body>

 
 
body 부분을 하나씩 살펴보자.
 
<section class="container">
먼저 <section> 태그는 다른 컨텐츠의 코드들과 섞이지 않기 위해 구분을 짓는데 쓰이는 태그이다.
<section> 태그 안의 코드들은 하나의 컨텐츠를 위해 쓰인것으로 보여지게끔 구분했다.
 
 
<div class="Title-container">
웹 페이지에 보여지는 제목 즉, 타이틀을 걸어둘 예정인데 이또한 <div> 태그를 사용해 보기좋게 요소들을 나누어 구분한다. <div> 태그는 아무런 기능을 가지지않으며 그저 코드를 레이아웃, 스타일링하기위해 사용된다.
따라서 이 div에는 "Title-container" 라는 class를 붙여넣어
이름그대로 이 div 태그 안에 코드들은 "제목을 위한 코드들이다" 라고 보기좋게 구분해놨다.
 
<img class="Title_img" src='img/title.png' alt="이미지">
제목 옆에 이미지를 하나 넣어 좀더 꾸며줄 생각으로 넣었다.
굳이 안넣어도 상관은 없다.
 
<h1 class="Title">To do List</h1>
<h1> 태그로 제목을 하나 만들어주고 CSS로 꾸미기 위해 class 속성을 넣어주었다.
 
<form class="form">
사용자의 입력을 받기위해 form 태그를 사용했다. 
<form> 태그는 사용자의 입력을 받기위한 태그인데 예시로 버튼이나 입력필드 등등 사용자가 서버측으로 값을 보내는걸 
받기 위한 태그이다. 여기 또한 class로 "form" 이란걸 붙여주었는데 딱히 어떠한 기능을 넣기위한 목적이 아닌 각 코드마다 어떠한 목적으로 사용되어있는지 그룹화하는걸 습관시키기 위해 넣어주었다. 이부분에선 굳이 class를 안넣어줘도 상관은 없다.
 

<label class="form_label" for="todo">오늘 해야할일은~</label>
<input class="form_input" type="text" id="todo" name="to-do" size="30" required>

label 태그를 사용해 입력필드를 생성한다. 
<label> 태그는 입력을 할수 있는 공간을 만들어주는 태그이며 for 속성과 같이쓰인다.
입력 필드가 있다는건 그 공간에 사용자가 입력을 할 수 있게끔 만들어주는 기능인데
이때 사용자가 입력한 값을 받아오는 역할이 <input>이다. 
즉, label 은 입력 공간을 만듬 - input 은 그 공간에 입력한 값을 가져옴.
이므로 둘이 한쌍을 이루어야한다. 이때 label과 input을 서로 연결시켜주는게 
label의 for 요소, input의 id 요소이다. for요소와 id요소를 서로 같게 적어주어 연결시켜준다.
다시 코드를 보자.
label 태그에 class로 "form_label"을 지정해주었고 for에는 "todo"를 적어주었다.
이후 바로 input 태그를 사용해 class는 "form_input"을 지정해주며 type은 "text"로 받아오겠다라고 지정해주었으며
id에는 label태그의 for속성과 똑같이 "todo"를 작성해 label태그와 연결시켜준다.
name 에는 "to-do"를 적었는데 name요소는 해당 입력필드의 이름을 지정해주는것이다.
이 이름은 데이터가 서버로 제출될때 서버는 name요소를 통해 데이터를 식별하는데 사용된다.
size는 "30"으로 입력 필드의 너비를 지정해준다.
required는 아무런 데이터가 없이 제출되는걸 막아주는 속성이다.
 
 
<button class="input_button"><span>입력!</span></button>
버튼을 만들어주고 class는 "input_button"을 넣어주었다.
보통 버튼이 있다는것은 버튼을 눌렀을때 이벤트가 발생하게끔 만들어지기 위해 있는 역할인데
class를 지정해주어야 js에서 이버튼에 지정된 class로 가져와 이벤트를 만들어지게끔 하기위해 
button 태그에는 class지정은 필수다.
 

<ul class="List">
</ul>
todolist에서 사용자가 입력칸에 입력을하고 버튼을 누르면 
목록에는 입력된 값이 출력이 되어야한다.
따라서 입력한 값들을 (<li> - 리스트아이템) 로 나타내기위해서 <ul>태그를 사용한다.
<li>태그는 단독으로 사용할수 없고 <ul> 태그나 <ol> 태그를 만나야만 리스트의 시작을 알리고 리스트의 각 항목을 전달한다.
 



CSS 작성

body, html {
	margin: 0;
	padding: 0;
	height: 100%;
}

body {
  background-image: url('img/background.jpg'); /* 실제 이미지 경로로 수정 */
  background-size: cover;
  background-position: center;
  display: flex;
  justify-content: center;
  align-items: center;
}

.Title_container {
  text-align: center; /* 텍스트를 중앙으로 정렬 */
  position: absolute; /* 절대 위치 */
  top: 10%; /* 상단에서 10% 떨어진 위치에 배치 */
  left: 50%; /* 왼쪽에서 50% 떨어진 위치에 배치 */
  transform: translateX(-50%); /* X축으로 -50% 이동하여 정확히 중앙에 배치 */
}


.Title {
  display: flex;
  font-size: 70px;
  margin: 0;
  justify-content: center; /* 가로 중앙 정렬 */
  margin-bottom: 80px;
}

.Title_img {
  margin-right: 20px; /* 제목과 이미지 사이의 간격을 주기 위함 */
  width: 150px;
  height: auto;
}


.todo-container {
  background: rgba(255, 255, 255, 0.7); /* 반투명 효과를 위해 rgba 사용 */
  width: 50%; /* 또는 원하는 너비 */
  min-height: 50vh; /* 또는 원하는 높이 */
  box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); /* 선택적 그림자 효과 */
  border-radius: 10px; /* 모서리를 둥글게 */
  /* 여기에 필요한 padding, margin 등을 추가 */
}

/* 기본 폰트 스타일을 설정합니다 */
h1, input, button {
  font-family: 'Arial', sans-serif;
}

/* 투두리스트 제목 스타일을 설정합니다 */
h1 {
  color: #333; /* 색상을 설정합니다 */
  text-align: center; /* 중앙 정렬합니다 */
}

/* 입력 필드 스타일을 설정합니다 */
input[type="text"] {
  width: 100%; /* 폭을 설정합니다 */
  padding: 0.5rem; /* 패딩을 줍니다 */
  margin: 0.5rem 0; /* 위아래 마진을 줍니다 */
  border: 1px solid #ddd; /* 테두리를 설정합니다 */
  border-radius: 5px; /* 모서리를 둥글게 합니다 */
}

/* 추가 버튼 스타일을 설정합니다 */
button {
  background-color: #5cb85c; /* 배경 색상을 설정합니다 */
  color: white; /* 폰트 색상을 설정합니다 */
  padding: 0.5rem 1rem; /* 패딩을 줍니다 */
  border: none; /* 테두리를 없앱니다 */
  border-radius: 5px; /* 모서리를 둥글게 합니다 */
  cursor: pointer; /* 마우스 커서를 손가락 모양으로 변경합니다 */
}

/* 추가 버튼을 호버했을 때의 스타일을 설정합니다 */
button:hover {
  background-color: #449d44; /* 배경 색상을 변경합니다 */
}

/* 투두리스트 항목 스타일을 설정합니다 */
ul {
  list-style-type: none; /* 기본 목록 스타일을 없앱니다 */
  padding: 0; /* 패딩을 재설정합니다 */
}

li {
  padding: 0.5rem 0; /* 패딩을 줍니다 */
  border-bottom: 1px solid #ddd; /* 아래쪽 테두리를 설정합니다 */
}

/* 마지막 항목의 테두리를 없앱니다 */
li:last-child {
  border-bottom: none;
}

.completed {
  text-decoration: line-through; /* 줄 긋기 */
  color: grey; /* 색상 변경 */
  opacity: 0.5; /* 투명도 변경 */
}

.List {
  cursor: pointer; /* 마우스 오버 시 커서 모양을 포인터(손가락 모양)로 변경 */
}

 
대부분 보면 알겠지만 html 안에서 class로 지정된것들을 css에서 꾸민다.
따라서 html안에 쓰이는 거의 모든 요소들은 class를 써는것이 일반적인 관행이다. 
추후에 재사용성이나 유지보수 등등이 용이하기 때문.

JavaScript 부분을 먼저 보고와서 css를 보면 좀더 코드를 이해하기 쉬울 것 같다.
 


JavaScript 작성

// DOM 요소를 선택합니다.
const addButton = document.querySelector('.input_button'); // 추가 버튼
const toDoInput = document.getElementById('todo'); // 텍스트 입력 필드
const toDoList = document.querySelector('.List'); // 할 일 목록이 표시될 리스트

// 할 일을 추가하는 함수입니다.
function addToDo() {
  // 입력 필드에서 텍스트 값을 가져옵니다.
  const toDoText = toDoInput.value.trim();

  // 입력 값이 비어있지 않은 경우에만 처리합니다.
  if (toDoText !== '') {
    // 새로운 리스트 항목을 생성합니다.
    const newToDo = document.createElement('li');
    newToDo.textContent = toDoText;

    // 생성한 리스트 항목을 리스트에 추가합니다.
    toDoList.appendChild(newToDo);

    // 입력 필드를 초기화합니다.
    toDoInput.value = '';
  }
}

// 추가 버튼에 클릭 이벤트 리스너를 추가합니다.
addButton.addEventListener('click', function(event) {
  event.preventDefault(); // 폼 제출을 방지합니다.
  addToDo(); // 할 일 추가 함수를 실행합니다.
});

// 추가적으로 키보드 이벤트 처리를 위한 이벤트 리스너를 설정할 수 있습니다.
toDoInput.addEventListener('keypress', function(event) {
  // 'Enter' 키가 눌렸을 때만 처리합니다.
  if (event.key === 'Enter') {
    event.preventDefault(); // 기본 이벤트를 방지합니다.
    addToDo(); // 할 일 추가 함수를 실행합니다.
  }
});

//여기에 목록중 한 항목을 선택하면 줄을 긋고 완료표시를 하게끔 만들것
toDoList.addEventListener('click', function(event) {
   if (event.target.tagName == 'LI') {
      event.target.classList.toggle('completed');
   }
});

 

 

//DOM 요소를 선택합니다.
const addButton = document.querySelector('.input_button'); // 추가 버튼
const toDoInput = document.getElementById('todo'); // 텍스트 입력 필드
const toDoList = document.querySelector('.List'); // 할 일 목록이 표시될 리스트

html에서 버튼요소에 class속성을 사용하여 "input_button" 이라는 이름을 지어준 이유가 여기 나온다.

버튼을 누르면 동작을 수행해야하기때문에 js에서 해당 요소를 찾기위하여 html 에서 클래스 속성을 부여한것.

 

먼저 document. 객체에 대해 알고있어야한다.

요소 선택하기:
document.getElementById('id'): 주어진 ID를 가진 요소를 찾습니다.
document.querySelector('.class'): 주어진 CSS 선택자와 일치하는 첫 번째 요소를 찾습니다.
document.querySelectorAll('.class'): 주어진 CSS 선택자와 일치하는 모든 요소를 찾습니다.

요소 생성하기:
document.createElement('tag'): 주어진 태그 이름으로 새 요소를 생성합니다.

이벤트 리스너 추가/제거하기:
document.addEventListener('event', handler): 문서에 이벤트 리스너를 추가합니다.
document.removeEventListener('event', handler): 문서에서 이벤트 리스너를 제거합니다.

문서 정보 접근하기:
document.title: 문서의 제목을 가져오거나 설정합니다.
document.URL: 문서의 전체 URL을 반환합니다.

문서 조작하기:
document.write(text): 문서에 텍스트를 쓰거나, HTML을 직접 삽입할 때 사용합니다.

document 객체는 객체 안에 있는 함수들을 사용하여 html 요소에 진입하기 위해 사용된다.

html 요소에 접근하고 조작할수 있게끔 만들어주는 객체이다.

따라서 우린 html코드에 있는 요소들을 가져와 동작할수 있게 만들기위해 document 객체를 사용하는것.

 

다시 코드로와서 봐보자.

 

 


//DOM 요소를 선택합니다.
const addButton = document.querySelector('.input_button'); // 추가 버튼
const toDoInput = document.getElementById('todo'); // 텍스트 입력 필드
const toDoList = document.querySelector('.List'); // 할 일 목록이 표시될 리스트

.input_button 이라는 클래스 이름을 가진 요소를 찾아와 addButton 이라는 변수를만들고 저장함.

todo 라는 id를 가진 요소를 찾아와 DoInput 이라는 변수를 만들고 이 변수에 저장함.

List 라는 클래스 이름을 가진 요소를 찾아와 toDoList 라는 변수를 만들고 이 변수에 저장함.

 

 

 

 

// 할 일을 추가하는 함수입니다.
function addToDo() {
  // 입력 필드에서 텍스트 값을 가져옵니다.
  const toDoText = toDoInput.value.trim();

  // 입력 값이 비어있지 않은 경우에만 처리합니다.
  if (toDoText !== '') {
    // 새로운 리스트 항목을 생성합니다.
    const newToDo = document.createElement('li');
    newToDo.textContent = toDoText;

    // 생성한 리스트 항목을 리스트에 추가합니다.
    toDoList.appendChild(newToDo);

    // 입력 필드를 초기화합니다.
    toDoInput.value = '';
  }
}
addToDo() 라는 함수를 만들고 이 함수안에 코드를 넣는 구조이다.

toDoInput.value.trim() = toDoInput 변수의 값(value)양옆 공백제거 (trim()) 하고 toDoText 라는 변수를 만들고 넣는다.

li 요소를 만들고(createElement('li'))   newToDo라는 변수를 만들어 할당시킨다. 따라서 newToDo 변수 안에 값들을 li요소로 저장될 것.

toDoText 변수 안에 있는 데이터를 newToDo 라는 변수에 텍스트(textContent)로 가져온다.

 

 

// 추가 버튼에 클릭 이벤트 리스너를 추가합니다.
addButton.addEventListener('click', function(event) {
  event.preventDefault(); // 폼 제출을 방지합니다.
  addToDo(); // 할 일 추가 함수를 실행합니다.
});

버튼에 클릭 이벤트함수를 넣고 함수코드 안에는 addToDo함수를 실행시킨다.

 

// 추가적으로 키보드 이벤트 처리를 위한 이벤트 리스너를 설정할 수 있습니다.
toDoInput.addEventListener('keypress', function(event) {
  // 'Enter' 키가 눌렸을 때만 처리합니다.
  if (event.key === 'Enter') {
    event.preventDefault(); // 기본 이벤트를 방지합니다.
    addToDo(); // 할 일 추가 함수를 실행합니다.
  }
});
클릭 뿐 아니라 엔터를 쳤을때도 이벤트가 발생하게끔 만들어지고 여기에도 addToDo함수를 실행시킨다.

 

//여기에 목록중 한 항목을 선택하면 줄을 긋고 완료표시를 하게끔 만들것
toDoList.addEventListener('click', function(event) {
   if (event.target.tagName == 'LI') {
      event.target.classList.toggle('completed');
   }
});

클릭 이벤트를 toDoList에 추가시킨다.

event.target은 이벤트의 타겟, 즉 이벤트를 실행시킨 요소를 가르킨다.

.tagName은 요소의 이름을 가져오는것.

따라서 

   if (event.target.tagName == 'LI') {

는 해당 요소가 Li 요소인지 확인하는 if 조건문.

 

      event.target.classList.toggle('completed');

classList 는 클래스에 접근할수있게 도와주는 역할이고

toggle은 classList의 메서드중 하나로 'completed' 클래스가 존재한다면 제거, 존재하지 않는다면 추가해주는 메서드이다. 

따라서 해당코드에선 completed 클래스를 부여하게된다. 

(css코드로 돌아가 보면 completed 클래스에는 줄을 긋게끔 만듦으로써

목록에 있는 Li 요소들을 클릭하면 todolist 페이지에서 목록에 해당줄을 줄 긋고 완료표시를 남기게 된다.)

 


 

완성작

이쁘게 꾸미는것좀 연습해야겠다...

'HTML , CSS , JS' 카테고리의 다른 글

<div>  (0) 2023.09.30
네비게이션 바 <nav> 구조  (1) 2023.09.11