DEV Community

Muhammad Rauf
Muhammad Rauf

Posted on

Create a Calendar in HTML and CSS

A calendar widget is the most important component for events-related websites. It helps users to see schedule or event information for a specific day or date. Besides this, a calendar is also used in the date picker, event scheduler, or general-purpose calendar widget projects. If you are working on such a project in which you need to implement a calendar widget, you are in the right place. In our last tutorial we learned Create Custom Scroll Bar Using CSS

In this tutorial, I’m going to explain how to create a calendar in HTML, CSS, and JavaScript.

Image description
You definitely need a calendar that you can design according to your needs. So, I’ll focus on the customization as well as creating the calendar widget by adding its assets to your project. Basically, this calendar widget doesn’t require a library or plugin as it’s purely written in JavaScript. Anyhow, it uses Font Awesome CSS for calendar navigation keys.

Before getting started with HTML, I would suggest you check out the demo page given below to see how the calendar works. You can highly customize its layout, current date, disabled date, and next/prev buttons navigation as you want.

The HTML Structure

In HTML, load the Reset CSS in order to clear the default browser’s formatting of HTML elements. Similarly, load Roboto fonts and Font Awesome CSS (for icons) by adding the following CDN links into the head tag of your webpage.

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css" rel="stylesheet" />
Enter fullscreen mode Exit fullscreen mode

We need to have a div element in which the calendar will be rendered dynamically. So, create a div element with a class name "softcard", place next/prev buttons, and a div element with an id "soft-btn" inside it.

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css" rel="stylesheet" />
<div class="softcard">
  <div class="calendar-bar">
    <button class="prev soft-btn"><i class="fas fa-chevron-left"></i></button>
    <div class="current-month"></div>
    <button class="next soft-btn"><i class="fas fa-chevron-right"></i></button>
  </div>
  <div class="calendar">
    <div class="weekdays-name">
      <div class="days-name">Sa</div>
      <div class="days-name">Su</div>
      <div class="days-name">Mo</div>
      <div class="days-name">Tu</div>
      <div class="days-name">We</div>
      <div class="days-name">Th</div>
      <div class="days-name">Fr</div>
    </div>
    <div class="calendar-days"></div>
  </div>
  <div class="goto-buttons">
    <button type="button" class="btn prev-year">Prev Year</button>
    <button type="button" class="btn today">Today</button>
    <button type="button" class="btn next-year">Next Year</button>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

You can place the above HTML structure anywhere in your webpage/app where you want to create a calendar widget.

Create CSS Styles for Calendar

After creating the Soft Card in HTML, now it’s time to style the calendar layout. Therefore, select the "calendar-bar" class and define its width, background, padding, and border properties as follows. You can set the custom background color according to your choice.

<style>
* {
  margin: 0;  padding: 0;}

body {
  height: 100vh;  background: #ddd;  display: flex;  justify-content: center;
  align-items: center;  font-family: "Quicksand", sans-serif;  user-select: none;
}

.softcard {  width: 316px;  height: fit-content;
  background: -webkit-linear-gradient(to right, #f7b733, #fc4a1a);  /* Chrome 10-25, Safari 5.1-6 */
  background: linear-gradient(to right, #f7b733, #fc4a1a); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
  border-radius: 20px;  box-shadow: 0px 0px 10px #000;
}

.calendar-bar {  display: flex;  justify-content: space-between;
  align-items: center;  padding: 20px;  padding-bottom: 15px;
  border-bottom: 19px;
}

.calendar-bar > .current-month {
  font-size: 20px;  font-weight: bold;  color: #ddd;
  background:#000;  padding:5px;  border-radius:10px;
}

.calendar-bar > [class$="soft-btn"] {
  width: 40px;  aspect-ratio: 1;  text-align: center;
  line-height: 40px;  font-size: 14px;  color: #000;
  background: #ddd;  border: none;  border-radius: 50%;
}

.weekdays-name,
.calendar-days {  display: flex;  flex-wrap: wrap;  padding-inline:18px;}
.weekdays-name {  padding-top: 12px;}

.calendar-days {  padding-bottom: 12px;}

.days-name,
[class$="-day"] {  width: 40px;  height: 40px;  color: #000;  text-align: center;
  line-height: 40px;  font-weight: 500;  font-size: 1rem;
}

.days-name {  color: #fff;  font-weight: 700;}

.current-day {
  background-color: #000;  color: #fff;
  border-radius: 50%;  font-weight: 700;  transition: 0.5s;  cursor: pointer;
}

.padding-day {
  color: #a5a5a5;  user-select: none;
}

.calendar-bar > [class$="soft-btn"]:hover,
.month-day:hover,
.btn:hover {
  border-radius:5px;  background-color:#f8f7fa;  color:#000;  border-radius:15px;
  transition: 0.1s;  cursor: pointer;

}

.calendar-bar > [class$="soft-btn"]:focus,
.month-day:focus,
.btn:focus {  border-radius:15px;  background-color: #000;  color: #ddd;
}

.goto-buttons {
  border-top: solid 2px yellow;  padding-block: 18px;  display: flex;
  justify-content: space-evenly;
}

.btn {
  background: #eee  border: none;  border-radius: 10px;
  padding: 11px 13px;  color:#000;  font-family: "Quicksand", sans-serif;
  font-weight: 600;  font-size: 0.9rem;  margin-right: 1px;  box-shadow: 0px 0px 0px #000;
}

</style>
Enter fullscreen mode Exit fullscreen mode

The JavaScript Function

Now everything is ready, finally, you only need to add the calendar JavaScript function into your project. So, add the following code between script tag before closing the body tag.

If you need to add more functionality to it you can modify the code accordingly. The purpose of each variable, object, and function is assigned, so you can easily understand what the calendar function does.

JavaScript Code:

var currentMonth = document.querySelector(".current-month");
var calendarDays = document.querySelector(".calendar-days");
var today = new Date();
var date = new Date();
currentMonth.textContent = date.toLocaleDateString("en-US", {month:'long', year:'numeric'});
today.setHours(0,0,0,0);
renderCalendar();
function renderCalendar(){
    const prevLastDay = new Date(date.getFullYear(),date.getMonth(),0).getDate();
    const totalMonthDay = new Date(date.getFullYear(),date.getMonth()+1,0).getDate();
    const startWeekDay = new Date(date.getFullYear(),date.getMonth(),1).getDay();
    calendarDays.innerHTML = "";
    let totalCalendarDay = 6 * 7;
    for (let i = 0; i < totalCalendarDay; i++) {
        let day = i-startWeekDay;
        if(i <= startWeekDay){
            // adding previous month days
            calendarDays.innerHTML += `<div class='padding-day'>${prevLastDay-i}</div>`;
        }else if(i <= startWeekDay+totalMonthDay){
            // adding this month days
            date.setDate(day);
            date.setHours(0,0,0,0);           
            let dayClass = date.getTime()===today.getTime() ? 'current-day' : 'month-day';
            calendarDays.innerHTML += `<div class='${dayClass}'>${day}</div>`;
        }else{
            // adding next month days
            calendarDays.innerHTML += `<div class='padding-day'>${day-totalMonthDay}</div>`;
        }    }}
document.querySelectorAll(".soft-btn").forEach(function (element) {
    element.addEventListener("click", function () {
        date = new Date(currentMonth.textContent);
        date.setMonth(date.getMonth() + (element.classList.contains("prev") ? -1 : 1));
        currentMonth.textContent = date.toLocaleDateString("en-US", {month:'long', year:'numeric'});
        renderCalendar();
    });});
document.querySelectorAll(".btn").forEach(function (element) {
    element.addEventListener("click", function () {
        let btnClass = element.classList;
        date = new Date(currentMonth.textContent);
        if(btnClass.contains("today"))
            date = new Date();
        else if(btnClass.contains("prev-year"))
            date = new Date(date.getFullYear()-1, 0, 1);
        else
            date = new Date(date.getFullYear()+1, 0, 1);
        currentMonth.textContent = date.toLocaleDateString("en-US", {month:'long', year:'numeric'});
        renderCalendar();
    });
});

Enter fullscreen mode Exit fullscreen mode

Hopefully from this article, you have learned how to make it. If there is any difficulty, you can let me know by discussing below.
Read in detail from our official website Create a Calendar in HTML and CSS

To see DEMO

Don’t forget to like and Follow to learn more amazing tutorials😉

Discussion (15)

Collapse
deathshadow60 profile image
deathshadow60 • Edited on

Your markup being endless pointless DIV with endless pointless classes is NOT semantically correct or useful for non-visual users. A calendar is tabular data. There is a semantic relationship between both rows and columns, and an obvious caption. Those buttons being scripting-only behaviors also means they probably don't belong in your markup in the first place.

Even if one were to slop out that garbage tag soup, the caption would be a numbered heading of the appropriate depth based on the page it's in, not a DIV.

Also... where the devil are you that Saturday is the first day of the week?

<table class="calendar">
    <caption>
        <button type="button" title="Previous Month"></button>
        ${month} ${year}
        <button type="button" title="Next Month"></button>
    </caption><thead>
        <tr>
            <th scope="col">Sun</th>
            <th scope="col">Mon</th>
            <th scope="col">Tue</th>
            <th scope="col">Wed</th>
            <th scope="col">Thu</th>
            <th scope="col">Fri</th>
            <th scope="col">Sat</th>
        </tr>
    </thead><tbody>
        <tr>
            <!-- days go here as TD -->
        </tr>
    </tbody><tfoot>
        <tr>
            <td colspan="7">
                <button type="button">Prev Year</button>
                <button type="button">Today</button>
                <button type="button">Next Year</button>
            </td>
        </tr>
    </tfoot>
</table>

There is NO reason to piss those classes all over it, or to avoid using a table in this case. Content dictates markup, and the obvious caption and row headings require the proper semantics. Otherwise you're telling accessibility and usability to sod off.

Just like how your linear-gradient color choices are a giant middle finger to accessibility too, being too close to middle luminance for black or white text to meet legibility minimums. Alongside all the PX metric fonts and element sizes that tells non-standard font-size users to kiss off. They're called EM, use 'em!

Collapse
softcodeon profile image
Muhammad Rauf Author

Hello, @deathshadow60 It seems you're not a professional yet. I have mentioned you can in post, Users can modify the colors, padding, marings, even classes name they can change as they want.

Where is problem with you?

I write this code with relation of my website. and yes I have right, I am a programmer I can write whatever I want, I can named classes, IDs as I would like. Also you mentioned. " Also... where the devil are you that Saturday is the first day of the week? " Show me where I wrote Saturday is the first day of a week. I wrote a simple markup they just only need to change the text and day what they want in first.

You can use td,tr,th etc for a table. I don't use them when I have div. You can use table format as you want. Please go forward and be professional. 😉😉😉

Collapse
deathshadow60 profile image
deathshadow60

First off I'm assuming some language barrier here, since I'm having a deuce of a time deciphering your reply.

That said, I'm not the professional? A PROFESSIONAL would put accessible metrics in their example. A PROFESSIONAL would actually care about accessibility and semantics. A PROFESSIONAL wouldn't use colours that are obviously in violation of the WCAG.

WHY?

1) Nubes who don't know any better will blindly copy it.

2) You could end up in violation of laws like the US ADA, UK EQA, French RGAA, etc, etc if you use it on the wrong types of websites.

3) It's a telltale for actual professionals that you don't know what you're doing.

A PROFESSIONAL does not blindly slop text into meaningless DIV, telling users of non-visual UA's to go plow themselves.

Not to use the "seniority fallacy", but I've been writing software for 40 years, 30 of that professionally, 20 of that using web technologies, and the past decade as an accessibility and efficiency consultant. This type of sloppy willy-nilly "I don't care about the rules" coding is EXACTLY the type of garbage that lands site owners in court, or knee-deep in unsustainable code, or alienating users in a manner that guarantees at best a money pit, at worst a complete failure.

One of the MANY reasons most startups fail in their first year.

A professional sure as shine-ola doesn't say "I can write whatever I want" when what they're spitting out is in complete violation of specifications, guidelines, and the very reason the languages being used exist. If you don't know what's wrong with just sleazing in a bunch of meaningless DIV you are by no means a professional at web development.

But then far too many people these days seem to confuse platitudes, soothing-syrup words, and a laissez-faire attitude with being "professional". IT ISN'T. Not by a longshot!. We're spending way too much time these days mollycoddling people who are doing serious damage.

Collapse
sumitdwievdi profile image
SumitDwievdi

Look at your code here, you typed Saturday as first day of the week👇

  <div class="days-name">Sa</div>
  <div class="days-name">Su</div>
  <div class="days-name">Mo</div>
  <div class="days-name">Tu</div>
  <div class="days-name">We</div>
  <div class="days-name">Th</div>
  <div class="days-name">Fr</div>
Enter fullscreen mode Exit fullscreen mode
Thread Thread
softcodeon profile image
Muhammad Rauf Author

Dear brother I have mentioned you can change class name, Ids, Text as you want. I just focused on code work. I hope it's working fine.

Thread Thread
sumitdwievdi profile image
SumitDwievdi

Ok

Collapse
arizona profile image
Arizona

Thanks! It looks beautiful keep it up. Please add comments in your code so we can easily understand.

Collapse
shadowruge profile image
izaias

Já está nos favoritos!

Collapse
softcodeon profile image
Muhammad Rauf Author

Obrigado, espero que você nos siga para atualizações futuras.

Collapse
aoikarasu profile image
Aoi Karasu

Well, Mr. Shadow, you do have valid points, but the way you lay them all out... You've got some serious issues, man. God bless!

Mr. Muhammad. Thank you for your contribution. I find the title of your article a bit misleading, though. It suggests you construct you calendar using pure HTML+CSS which sparkled the curiousity in me, and was the very reason I came to read it. Yet , you use JavaScript extensively here. Would you care to update your title, please? Cheers!

Collapse
mrmannu profile image
mrmannu

Great info and it was very helpful....
json file over at CodeSandbox for specifics. by tweakdoor.info/
Step 1: Start with the basic markup and styles. Let's start with creating a basic template for our calendar. ...
Step 2: Setting up current month calendar. ...
Step 3: Creating the calendar grid. ...
Step 4: Show calendar dates. ...
Step 5: Select current month.

Collapse
amritangshug profile image
Amritangshu Goswami

Why does the code use JS? I thought it only uses HTML and CSS. It is possible to create a Calender with just basic HTML and CSS.

Collapse
arizona profile image
Arizona

I thinks it's not because we need to get current date by using JS. I think it's still not possible to get current date in CSS. If you know please let's know. Thank you.

Collapse
andrew_mamus profile image
Akpeghughu Andrew

You can not get current date with CSS

Collapse
kekelidev profile image
Aaron Kofi Gayi • Edited on

You did a good but the semantics were off. And also a calendar widget is useful if its data can be passed into a form field other than that it is just a a white elephant to go through all the troubles whilst browsers provide a native calendar.