
1. 배경 이미지
- 전체 화면으로 변경
- 창 크기에 따라 이미지 조절
- 젤 뒤에 위치
/* 배경 이미지 설정 */
#bg-img {
position: fixed; /* 이미지를 화면에 고정하여 스크롤 시에도 유지 */
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: fill;
object-position: center;
z-index: -1; /* 다른 모든 요소의 뒤에 위치 */
}

2. login-form
- 화면의 가운데 위치
- 입력, 버튼 수정
- login-form에 hodden이 추가되었지만 사라지지 않고 텍스트 뒤에 위치해있음 → !important;

.hidden {
display: none !important; // 우선 순위 높이기
}
/* 로그인 폼의 스타일 */
.login-form {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
align-items: center; /* 수직 중앙 정렬 */
gap: 10px;
font-size: 20px;
border: none; /* 기본 버튼 테두리 제거 */
}
/* 로그인 폼의 입력 필드 스타일 */
.login-form input {
padding: 20px; /* 입력 필드 안에 여백 추가 */
font-size: 30px; /* 입력 필드의 텍스트 폰트 크기를 30px로 설정 */
border: 1px solid #ccc; /* 기본 테두리 스타일 */
border-radius: 5px; /* 입력 필드 모서리 둥글게 설정 */
box-sizing: border-box; /* 패딩을 너비 계산에 포함시킴 */
}
/* 로그인 폼의 버튼 스타일 */
.login-form button {
padding: 20px;
font-size: 25px;
cursor: pointer; /* 버튼 위에 마우스를 올리면 포인터로 변경 */
background-color: #3c7cc0;
color: white; /* 버튼 텍스트 색상 설정 */
border-radius: 5px;
}
.login-form button:hover {
background-color: #0056b3; /* 버튼 호버 시 배경색 변경 */
}

3. 인사말
- 화면 위쪽에 위치
- 크기, 테두리 수정
/* 인사말 스타일 */
#greeting {
position: fixed;
top: 15%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 50px;
padding: 20px;
text-align: center; /* 텍스트 가운데 정렬 */
border: none;
}

4. 명언
- 아래에 위치
- 불투명한 배경색 적용
- 명언과 저자 줄, 크기 변경
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<form class="login-form hidden" id="login-form">
<input
required
maxlength="15"
type="text"
placeholder="What is your name?" />
<button type="submit">로그인</button>
</form>
<h2 id="clock">00:00:00</h2>
<h1 class="hidden" id="greeting"></h1>
<form id="todo-form">
<input type="text" placeholder=" 할일을 쓰고 enter를 누르세요" required/>
</form>
<ul id="todo-list"></ul>
<div id="quote">
<div></div>
<div></div>
</div>
<div id="weather">
<span></span>
<span></span>
</div>
<script src="js/greetings.js"></script>
<script src="js/clock.js"></script>
<script src="js/quotes.js"></script>
<script src="js/background.js"></script>
<script src="js/todo.js"></script>
<script src="js/weather.js"></script>
</body>
</html>
const quotes = [
{
quote: "The only way to do great work is to love what you do",
author: "Steve Jobs"
},
{
quote: "Life is what happens when you're busy making other plans",
author: "John Lennon"
},
{
quote: "The purpose of our lives is to be happy",
author: "Dalai Lama"
},
{
quote: "Get busy living or get busy dying",
author: "Stephen King"
},
{
quote: "You have within you right now, everything you need to deal with whatever the world can throw at you",
author: "Brian Tracy"
},
{
quote: "Believe you can and you're halfway there",
author: "Theodore Roosevelt"
},
{
quote: "The best way to predict the future is to invent it",
author: "Alan Kay"
},
{
quote: "Your time is limited, don't waste it living someone else's life",
author: "Steve Jobs"
},
{
quote: "If life were predictable it would cease to be life, and be without flavor",
author: "Eleanor Roosevelt"
},
{
quote: "In the end, we will remember not the words of our enemies, but the silence of our friends",
author: "Martin Luther King Jr"
}
];
const quote = document.querySelector("#quote div:first-child");
const author = document.querySelector("#quote div:last-child");
const todayQuote = quotes[Math.floor(Math.random() * quotes.length)];
quote.innerText = todayQuote.quote;
author.innerText = `by ${todayQuote.author}`;
/*명언 스타일*/
#quote {
position: fixed; /* 화면에 고정 */
bottom: 5%; /* 바닥에서 20% 위치 */
width: 100%;
left: 50%; /* 화면의 가운데 위치 */
transform: translateX(-50%); /* 가운데 정렬 */
text-align: center; /* 텍스트 가운데 정렬 */
color: white; /* 텍스트 색상 (원하는 색상으로 변경 가능) */
padding: 10px; /* 텍스트 주변에 여백 추가 */
background: rgba(0, 0, 0, 0.5); /* 반투명 배경 (선택사항) */
border-radius: 5px; /* 모서리 둥글게 (선택사항) */
}

5. 시계
- am, pm 추가하고 맨 앞에 오게 하기
- 왼쪽 여백두기
const clock = document.querySelector("h2#clock");
function getClock() {
const date = new Date();
let hours = date.getHours();
const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, "0");
// AM/PM 형식으로 변환
const ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12; // 시간 0을 12로 변환
// 두 자리 숫자로 포맷
const formattedHours = String(hours).padStart(2, "0");
clock.innerText = `${ampm} ${formattedHours}:${minutes}:${seconds}`;
}
getClock();
setInterval(getClock, 1000); // 1초마다 실행
/*시계 스타일*/
#clock {
position: fixed;
left: 3%;
}

6. To Do List
- todo-form
- 위쪽과 왼쪽 여백두기
- placeholder 변경
- 테두리, 배경 변경
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<form class="login-form hidden" id="login-form">
<input
required
maxlength="15"
type="text"
placeholder="What is your name?" />
<button type="submit">로그인</button>
</form>
<h2 id="clock">00:00:00</h2>
<h1 class="hidden" id="greeting"></h1>
<form id="todo-form">
<input type="text" placeholder="✏️ todo 리스트 작성하기!" required/>
</form>
<ul id="todo-list"></ul>
<div id="quote">
<div></div>
<div></div>
</div>
<div id="weather">
<span></span>
<span></span>
</div>
<script src="js/greetings.js"></script>
<script src="js/clock.js"></script>
<script src="js/quotes.js"></script>
<script src="js/background.js"></script>
<script src="js/todo.js"></script>
<script src="js/weather.js"></script>
</body>
</html>
/* todo-form 스타일 설정 */
#todo-form {
position: fixed;
top: 25%;
left: 10%;
padding: 20px;
text-align: center;
border: none;
border-radius: 10px;
}
/* 입력 필드 스타일 설정 */
#todo-form input {
padding: 15px;
font-size: 20px;
border: 1px solid #ccc;
border-radius: 5px;
box-sizing: border-box;
width: 100%;
margin-top: 10px;
}

- todo-list
- todo-form 밑에 위치
- x버튼 배경, 테두리 변경
- 줄 간격 변경
#todo-list{
position: fixed;
top: 32%;
left: 12%;
padding: 15px;
}

- 페이지네이션
- 10개까지가 1개의 페이지
- 페이지네이션 버튼 추가
- 이벤트 추가
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<form class="login-form hidden" id="login-form">
<input
required
maxlength="15"
type="text"
placeholder="What is your name?" />
<button type="submit">로그인</button>
</form>
<h2 id="clock">00:00:00</h2>
<h1 class="hidden" id="greeting"></h1>
<form id="todo-form">
<input type="text" placeholder="✏️ todo 리스트 작성하기!" required/>
</form>
<ul id="todo-list"></ul>
<!-- Add this section in your HTML -->
<div id="pagination">
<button id="prev-page" disabled>이전</button>
<span id="page-info">1</span>
<button id="next-page">다음</button>
</div>
<div id="quote">
<div></div>
<div></div>
</div>
<div id="weather">
<span></span>
<span></span>
</div>
<script src="js/greetings.js"></script>
<script src="js/clock.js"></script>
<script src="js/quotes.js"></script>
<script src="js/background.js"></script>
<script src="js/todo.js"></script>
<script src="js/weather.js"></script>
</body>
</html>
// JavaScript (script.js)
document.addEventListener("DOMContentLoaded", () => {
const toDoForm = document.getElementById("todo-form");
const toDoInput = toDoForm.querySelector("input");
const toDoList = document.getElementById("todo-list");
const prevPageButton = document.getElementById("prev-page");
const nextPageButton = document.getElementById("next-page");
const pageInfo = document.getElementById("page-info");
const TODOS_KEY = "todos";
const ITEMS_PER_PAGE = 10;
let toDos = [];
let currentPage = 1;
function saveToDos() {
localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}
function deleteToDo(event) {
const li = event.target.parentElement;
li.remove();
toDos = toDos.filter(toDo => toDo.id !== parseInt(li.id));
saveToDos();
updatePagination();
}
function paintToDoList() {
toDoList.innerHTML = "";
const start = (currentPage - 1) * ITEMS_PER_PAGE;
const end = start + ITEMS_PER_PAGE;
const toDosToDisplay = toDos.slice(start, end);
toDosToDisplay.forEach(paintToDo);
prevPageButton.disabled = currentPage === 1;
nextPageButton.disabled = end >= toDos.length;
pageInfo.innerText = `${currentPage}`;
}
function paintToDo(newToDo) {
const li = document.createElement("li");
li.id = newToDo.id;
const span = document.createElement("span");
span.innerText = newToDo.text;
const button = document.createElement("button");
button.innerText = "❌";
button.addEventListener("click", deleteToDo);
li.appendChild(span);
li.appendChild(button);
toDoList.appendChild(li);
}
function handleToDoSubmit(event) {
event.preventDefault();
const newToDo = toDoInput.value;
toDoInput.value = "";
const newTodoObj = {
text: newToDo,
id: Date.now(),
}
toDos.push(newTodoObj);
saveToDos();
updatePagination();
}
function updatePagination() {
const totalPages = Math.ceil(toDos.length / ITEMS_PER_PAGE);
if (currentPage > totalPages) {
currentPage = totalPages;
}
paintToDoList();
}
function handlePagination(event) {
if (event.target.id === "next-page") {
currentPage++;
} else if (event.target.id === "prev-page") {
currentPage--;
}
updatePagination();
}
toDoForm.addEventListener("submit", handleToDoSubmit);
prevPageButton.addEventListener("click", handlePagination);
nextPageButton.addEventListener("click", handlePagination);
const savedToDos = localStorage.getItem(TODOS_KEY);
if (savedToDos !== null) {
toDos = JSON.parse(savedToDos);
updatePagination();
} else {
toDos = [];
}
});
/* 페이지네이션 버튼 스타일 설정 */
#pagination {
position: fixed;
bottom: 26%;
left: 14%;
}
#pagination button {
padding: 10px 10px;
margin: 0 10px;
font-size: 10px;
cursor: pointer;
border: none;
border-radius: 5px;
background-color: #f0f0f0;
}

7. 날씨
- 시간 밑에 표시
- 소수 첫째자리까지 표시
- 날씨 이모지 추가
const API_KEY = "46c42ba74d2d22c044c652e13464ef9b";
// 날씨 상태에 따른 이모지 매핑
const weatherEmojis = {
"Clear": "☀️",
"Clouds": "☁️",
"Rain": "🌧️",
"Drizzle": "🌦️",
"Thunderstorm": "⛈️",
"Snow": "❄️",
"Mist": "🌫️",
"Smoke": "🌫️",
"Haze": "🌫️",
"Fog": "🌁",
"Sand": "🌪️",
"Dust": "🌫️",
"Ash": "🌋",
"Squall": "🌫️",
"Tornado": "🌪️"
};
function onGeoOk(position) {
const lat = position.coords.latitude;
const lon = position.coords.longitude;
const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`;
fetch(url)
.then(response => response.json())
.then(data => {
const weather = document.querySelector("#weather span:first-child");
const city = document.querySelector("#weather span:last-child");
city.innerText = data.name;
// 온도를 소수 첫째 자리까지 표시
const temp = data.main.temp.toFixed(1);
// 날씨 상태에 따른 이모지 가져오기
const weatherCondition = data.weather[0].main;
const emoji = weatherEmojis[weatherCondition] || "🌥️"; // 기본 이모지
weather.innerText = `${weatherCondition} ${emoji} / ${temp}°C`;
});
}
function onGeoError() {
alert("위치를 찾을 수 없어요. 날씨를 찾을 수 없어요ㅜ");
}
navigator.geolocation.getCurrentPosition(onGeoOk, onGeoError);
/*날씨 스타일 설정*/
#weather {
position: fixed; /* 화면에 고정 */
top: 7%;
left: 3%;
font-size: 20px;
}


Share article