Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div class="calendar">
		<div class="calendar__year">
			<div class="JS-yearControl--prev calendar__prev calendar__year-prev"
			 data-move="decrement" data-storage="year">
				<i class="fa fa-chevron-circle-left" aria-hidden="true"></i>
			</div>
			<div class="JS-yearControl--next calendar__next calendar__year-next"
			 data-move="increment" data-storage="year">
				<i class="fa fa-chevron-circle-right" aria-hidden="true"></i>
			</div>
			<input id="year" value="" type="text"
			 readonly class="calendar__year-value">
		</div>

		<div class="calendar__month">
			<div class="JS-monthControl--prev calendar__prev calendar__month-prev"
			 data-move="decrement" data-storage="month">
				<i class="fa fa-chevron-circle-left" aria-hidden="true"></i>
			</div>
			<div class="JS-monthControl--next calendar__next calendar__month-next"
			 data-move="increment" data-storage="month">
				<i class="fa fa-chevron-circle-right" aria-hidden="true"></i>
			</div>
			<input id="month" value="" type="text"
			 readonly class="calendar__month-value">
		</div>

		<table id="JS-calendarDays" class="calendar__days">
		</table>
	</div>
              
            
!

CSS

              
                @import url(https://fonts.googleapis.com/css?family=Roboto+Slab);

body,
html {
	font-family: 'Roboto Slab', serif;
}

.calendar {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	box-shadow: 0 0 1px 0 #cecece, 0 3px 8px #cecece;
	padding: 20px;
	box-sizing: border-box;
	border-radius: 5px;
}

.calendar__days {
	width: 250px;
	height: 240px;
}

.day-of-the-week {
	text-align: center;
	padding: 5px;
	font-weight: 400;
	width: 30px;
}

.day-of-the-month {
	text-align: center;
	padding: 5px;
	cursor: pointer;
	transition: all .1s ease-in-out;
	border-radius: 2px;
}

.day-of-the-month:hover {
	color: #ffffff;
	background: #dea291;
}


.day-of-the-month--weekend {
	background: #93e0d6;
	color: #ffffff;
}

.day-of-the-month--today {
	background: #de5a4c;
	color: #ffffff;
}

.calendar__year,
.calendar__month {
	display: block;
	text-align: center;
	width: 100%;
	margin-bottom: 20px;
	position: relative;
}

input[type="text"] {
	border: none;
	text-align: center;
	padding: 0;
	display: inline-block;
	padding: 5px;
	outline: none;
	font-family: 'Roboto Slab', serif;
	font-size: 18px;
}

.calendar__prev,
.calendar__next {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	cursor: pointer;
	font-size: 20px;
	color: lightblue;
	transition: all .3s ease-in-out;
}

.calendar__prev:hover,
.calendar__next:hover {
	color: lightcoral;
}

.calendar__prev {
	left: 10px;
}

.calendar__next {
	left: auto;
	right: 10px;
}
              
            
!

JS

              
                'use strict';

let daysOfTheWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
let months = [
	'January',
	'February',
	'March',
	'April',
	'May',
	'June',
	'July',
	'August',
	'September',
	'October',
	'November',
	'December'
];
let yearNode = document.getElementById('year');
let currYear = yearNode.value || new Date().getFullYear();
let monthNode = document.getElementById('month');
let currMonth = monthNode.value || new Date().getMonth();

/*  Set current year and month as default values in inputs 
*	@yearNode: input with id 'year'
*	@monthNode: input with id 'month'
 */
yearNode.value = currYear;
monthNode.value = months[currMonth];


createCalendar('JS-calendarDays', currYear, currMonth + 1, daysOfTheWeek);

['JS-monthControl--next', 'JS-monthControl--prev', 'JS-yearControl--prev', 'JS-yearControl--next'].forEach(elem => {
	document.getElementsByClassName(elem)[0].onclick = (e) => {
		e.preventDefault();

		let target = document.getElementsByClassName(elem)[0].getAttribute('data-storage');

		if (target == 'year') {
			changeCurrDate('year', elem);
		}
		else if (target == 'month') {
			changeCurrDate('month', elem);
		}

		createCalendar('JS-calendarDays', +yearNode.value, months.indexOf(monthNode.value) + 1, daysOfTheWeek);
	}
});

/* Initialize a calendar creator : params = id, year, month, weekDays
*	@id: id of a block where the function will render the calendar
*	@year: set a year of a required date
*	@month: set a month of a required date
*	@weekDays: a stack of the weekday names
 */
function createCalendar(id, year, month, weekDays) {
	let mon = month - 1;
	let date = new Date(year, mon);
	let html = '<tr>' + generateDaysOfTheWeek(weekDays) + '</tr><tr>';

	// Generate days of the last month up to the current day of the week
	for (let i = 0; i < getWeekDay(date); i++) {
		html += '<td></td>';
	}

	html += generateCalendarDays(date, mon);

	// Generate days of the next month up to the current day of the week
	if (getWeekDay(date) != 0) {
		for (let i = getWeekDay(date); i < 7; i++) {
			html += '<td></td>';
		}
	}

	document.getElementById(id).innerHTML = html;
}

/* getWeekDay(date): calculate a day of the week 
*	@date: 
 */
function getWeekDay(date) {
	let day = date.getDay();

	// If the day == 0 it means the is Sunday and it should follow by Saturday
	if (day == 0) day = 7;

	return day - 1;
}

/* generateDaysOfTheWeek(days): generate short view of the day of the week
*	@days: stack of the days for the week
*/
function generateDaysOfTheWeek(days) {
	days = days.map(d => '<th class="day-of-the-week">' + d.slice(0, 3) + '</th>').join('');

	return days;
}

/* The calendar cell generator : params = date, month
*	@date: a date required for display
*	@month: a month required for display
*/
function generateCalendarDays(date, month) {
	let html = '';

	while (date.getMonth() == month) {
		let dayWeekend = '<td class="day-of-the-month day-of-the-month--weekend" title="Weekend">' + date.getDate() + '</td>';
		let day = '<td class="day-of-the-month">' + date.getDate() + '</td>';

		// If installed date is equal to current date
		if (new Date().getFullYear() == date.getFullYear() && new Date().getMonth() == date.getMonth() && new Date().getDate() == date.getDate()) {
			day = '<td class="day-of-the-month day-of-the-month--today" title="Today">' + date.getDate() + '</td>';
		}

		// Detecting weekends in the running date
		html += getWeekDay(date) % 7 == 6 || getWeekDay(date) % 7 == 5 ? dayWeekend : day;

		// Generate new cell row each 7 cells (each week)
		if (getWeekDay(date) % 7 == 6) html += '</tr><tr>';

		date.setDate(date.getDate() + 1);
	}

	return (html);
}

/* changeCurrdate(id, elem) : update rendered year and month at the calendar
*	@id: id of the element which update is required
*	@elem: class of the element that is a trigger to update #id element
 */
function changeCurrDate(id, elem) {
	let trigger = document.getElementsByClassName(elem)[0];
	let move = trigger.getAttribute('data-move'); // Coordinate a target of the trigger @id

	if (id == 'year' && move == 'increment' && +document.getElementById(id).value < 2500) {
		document.getElementById(id).value = incrementYear(id);
	}
	else if (id == 'year' && move == 'decrement' && +document.getElementById(id).value > 1970) {
		document.getElementById(id).value = decrementYear(id);
	}
	else if (id == 'month' && move == 'increment') {
		document.getElementById(id).value = nextMonth(id);
	}
	else if (id == 'month' && move == 'decrement') {
		document.getElementById(id).value = prevMonth(id);
	}

	/* prevMonth(id): generate a following month by the current month
	*	@id: indetificator of the element which takes an update
	 */
	function prevMonth(id) {
		let currNewMonth = document.getElementById(id).value;
		let prevNewMonth = months[months.indexOf(currNewMonth) - 1];

		if (months.indexOf(currNewMonth) <= 0) {
			document.getElementById('year').value = decrementYear('year');
			prevNewMonth = months[11];
		}

		return prevNewMonth;
	}

	/* nextMonth(id): generate a previous month by the current month
	*	@id: indetificator of the element which takes an update
	 */
	function nextMonth(id) {
		let currNewMonth = document.getElementById(id).value;
		let nextNewMonth = months[months.indexOf(currNewMonth) + 1];

		if (months.indexOf(currNewMonth) >= months.length - 1) {
			document.getElementById('year').value = incrementYear('year');
			nextNewMonth = months[0];
		};

		return nextNewMonth;
	}

	/* incrementYear(id): generate a following year by the current year
	*	@id: indetificator of the element which takes an update
	 */
	function incrementYear(id) {
		return +document.getElementById(id).value + 1;
	}

	/* decrementYear(id): generate a following year by the current year
	*	@id: indetificator of the element which takes an update
	 */
	function decrementYear(id) {
		return +document.getElementById(id).value - 1;
	}
}


              
            
!
999px

Console