1. 현재 년도 & 월
2. 좌우 이동 화살표 - 이전/다음 달 이동
3. 가장 윗 줄은 요일
4. 일요일은 빨간색, 토요일은 파란색 글자, Today는 특별한 색
5. 이전 달, 다음 달 날짜는 반투명
<div class="calendar">
<div class="header">
<div class="year-month"></div>
<div class="nav">
<button class="nav-btn go-prev"><</button>
<button class="nav-btn go-today">Today</button>
<button class="nav-btn go-next">></button>
</div>
</div>
<div class="main">
<div class="days">
<div class="day">일</div>
<div class="day">월</div>
<div class="day">화</div>
<div class="day">수</div>
<div class="day">목</div>
<div class="day">금</div>
<div class="day">토</div>
</div>
<div class="dates"></div>
</div>
</div>
화면 | 설명 |
---|---|
![]() | 1. <div class="header"> 와 <div class="main"> 로 구분 : header : 현재 달 & 이전/다음 달 이동 : main : 이번 달 날짜 2. <div class="year-month"></div> : 월 변경 되는 부분 3. <div class="nav"><button class="nav-btn go-prev"><</button><button class="nav-btn go-today">Today</button><button class="nav-btn go-next">></button></div> : 좌우 화살표 < > 를 통한 이전 달, 다음 달 이동 |
Date()
를 이용해 날짜 데이터 받아오기const date = new Date();
const viewYear = date.getFullYear();
const viewMonth = date.getMonth();
.year-month
채우기document.querySelector('.year-month').textContent = `${viewYear}년 ${viewMonth + 1}월`;
querySelector 이용해 year-month에 접근해 연도와 월 채우기
Date()
에 파라미터 0
을 전달해 지난 달의 마지막 날 객체 생성0번째
날짜를 뽑아 이번달의 마지막 날 객체 생성const prevLast = new Date(viewYear, viewMonth, 0);
const thisLast = new Date(viewYear, viewMonth + 1, 0);
const PLDate = prevLast.getDate();
const PLDay = prevLast.getDay();
const TLDate = thisLast.getDate();
const TLDay = thisLast.getDay();
// 1) 배열 생성
const prevDates = [];
const thisDates = [...Array(TLDate + 1).keys()].slice(1);
const nextDates = [];
// 2) 받아온 날짜를 기준으로 배열에 day 숫자 값을 채워줌
if (PLDay !== 6) {
for (let i = 0; i < PLDay + 1; i++) {
prevDates.unshift(PLDate - i);
}
}
for (let i = 1; i < 7 - TLDay; i++) {
nextDates.push(i);
}
//3) HTML에 채우기
const dates = prevDates.concat(thisDates, nextDates);
dates.forEach((date, i) => {
dates[i] = `<div class="date">${date}</div>`;
})
document.querySelector('.dates').innerHTML = dates.join('');
화면1 | 화면2 |
---|---|
![]() | ![]() |
/*전체 태그의 margin, padding 없애기*/
* {
margin: 0;
padding: 0;
font-family: sans-serif;
box-sizing: border-box;
}
/*달력을 가운데 정렬 : display와 min-height 설정*/
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
/*달력의 크기 설정*/
.calendar {
width: 600px;
margin: 50px;
/*margin 통해 브라우저 작아졌을 때 자연스럽게 하기 위해*/
}
/*header 부분 설정*/
.header {
display: flex;
/*header안 year-month와 nav 가로 나열*/
justify-content: space-between;
align-items: center;
}
.year-month {
font-size: 35px;
}
.nav {
display: flex;
/*nav 버튼 정렬 위해*/
border: 1px solid #333333;
border-radius: 5px;
/*테두리 그리고 라운딩*/
}
.nav-btn {
width: 28px;
height: 30px;
border: none;
font-size: 16px;
line-height: 34px;
background-color: transparent;
cursor: pointer;
}
.go-today {
width: 75px;
/*today라는 긴 글자 들어가야함으로 너비 크게*/
border-left: 1px solid #333333;
border-right: 1px solid #333333;
}
화면 |
---|
![]() |
.days {
display: flex;
margin: 25px 0 10px;
}
.day {
width: calc(100% / 7);
text-align: center;
}
.dates {
display: flex;
flex-flow: row wrap;
height: 500px;
border-top: 1px solid #333333;
border-right: 1px solid #333333;
}
.date {
width: calc(100% / 7);
padding: 15px;
text-align: right;
border-bottom: 1px solid #333333;
border-left: 1px solid #333333;
}
화면 |
---|
![]() |
.day:nth-child(7n + 1),
.date:nth-child(7n + 1) {
color: #D13E3E;
/*일요일은 빨간색*/
}
.day:nth-child(7n),
.date:nth-child(7n) {
color: #396EE2;
/*토요일은 파란색*/
}
화면 |
---|
![]() |
// Date 객체 생성
const date = new Date();
const renderCalendar = () => {
const viewYear = date.getFullYear();
const viewMonth = date.getMonth();
// year-month 채우기
document.querySelector('.year-month').textContent = `${viewYear}년 ${viewMonth + 1}월`;
// 지난 달 마지막 Date, 이번 달 마지막 Date
const prevLast = new Date(viewYear, viewMonth, 0);
const thisLast = new Date(viewYear, viewMonth + 1, 0);
const PLDate = prevLast.getDate();
const PLDay = prevLast.getDay();
const TLDate = thisLast.getDate();
const TLDay = thisLast.getDay();
// Dates 기본 배열들
const prevDates = [];
const thisDates = [...Array(TLDate + 1).keys()].slice(1);
const nextDates = [];
// prevDates 계산
if (PLDay !== 6) {
for (let i = 0; i < PLDay + 1; i++) {
prevDates.unshift(PLDate - i);
}
}
// nextDates 계산
for (let i = 1; i < 7 - TLDay; i++) {
nextDates.push(i)
}
// Dates 합치기
const dates = prevDates.concat(thisDates, nextDates);
// Dates 정리
dates.forEach((date, i) => {
dates[i] = `<div class="date">${date}</div>`;
})
// Dates 그리기
document.querySelector('.dates').innerHTML = dates.join('');
}
renderCalendar();
let date = new Date();
goToday 함수에 서 date 값을 재할당해야해서 const
가 아닌 let
으로 변경
const prevMonth = () => {
date.setMonth(date.getMonth() - 1);
renderCalendar();
}
const nextMonth = () => {
date.setMonth(date.getMonth() + 1);
renderCalendar();
}
const goToday = () => {
date = new Date();
renderCalendar();
}
<div class="nav">
<button class="nav-btn go-prev" onclick="prevMonth()"><</button>
<button class="nav-btn go-today" onclick="goToday()">Today</button>
<button class="nav-btn go-next" onclick="nextMonth()">></button>
</div>
이전달 | 오늘 | 다음달 |
---|---|---|
![]() | ![]() | ![]() |
// Dates 정리
const firstDateIndex = dates.indexOf(1);
const lastDateIndex = dates.lastIndexOf(TLDate);
dates.forEach((date, i) => {
const condition = i >= firstDateIndex && i < lastDateIndex + 1
? 'this'
: 'other';
dates[i] = `<div class="date"><span class="${condition}">${date}</span></div>`;
})
이전달/다음달 날짜에 CSS 부여하기 위해 HTML 태그 수정
.other {
opacity: 0.3;
}
투명도 스타일 부여
화면 |
---|
![]() |
// 오늘 날짜 그리기
const today = new Date();
//오늘 날짜에 맞는 Date 객체 생성
if (viewMonth === today.getMonth() && viewYear === today.getFullYear()) {
//viewMonth와 viewYear가 today와 동일한지 비교
for (let date of document.querySelectorAll('.this')) {
//동일한 경우 this 클래스 가진 태그 다 찾아내고
if (+date.innerText === today.getDate()) {
//해당 태그의 문자 값을 숫자로 변경해 오늘 날짜오 비교하고
date.classList.add('today');
//today 클래스 부여
break;
//today는 한개 뿐이라 더이상 탐색 필요 없으니 탈출
}
}
}
.today {
position: relative;
color: #FFFFFF;
}
.today::before {
position: absolute;
top: 50%;
left: 50%;
z-index: -1;
display: block;
width: 30px;
height: 30px;
background-color: #FF0000;
border-radius: 50%;
transform: translate(-50%, -50%);
content: '';
}
today 스타일 부여
화면 |
---|
![]() |