PHP AJAX Calendar

PHP AJAX Calendar

17 169835
PHP AJAX Calendar

PHP AJAX Calendar

The php calendar is an integral part of many websites, frequently, this is one of numerous jQuery calendar plugins, but it can also be implemented using php. Today I will show you how to create a monthly calendar with the ability to scroll (left and right arrows) through the months using AJAX technology. Besides of ajax, this calendar has another important advantage, it is mobile-ready calendar with the responsive layout. Before we start writing code, I recommend that you look at our demo to see what we’re going to do.


PHP AJAX Calendar

Live Demo

Folder structure

In the beginning, let’s define a clear folder structure for all of our following files

  • css – for all css files
  • images – for all possible images
  • templates – for all template files

Step 1. HTML

We are not going to use any specific template system (like Smarty), we are only about to use simple html templates with own replacement keys


<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
    <title>PHP AJAX Calendar</title>
    <!-- add styles and scripts -->
    <link href="css/styles.css" rel="stylesheet" type="text/css" />
    <script src=""></script>
    <div id="calendar">

This is a very simple template for our index page where we defined the parent container for our calendar. Another template will be used as an inner container of the calendar:


<div class="navigation">
    <a class="prev" href="index.php?month=__prev_month__" onclick="$('#calendar').load('index.php?month=__prev_month__&_r=' + Math.random()); return false;"></a>
    <div class="title" >__cal_caption__</div>
    <a class="next" href="index.php?month=__next_month__" onclick="$('#calendar').load('index.php?month=__next_month__&_r=' + Math.random()); return false;"></a>
        <th class="weekday">sun</th>
        <th class="weekday">mon</th>
        <th class="weekday">tue</th>
        <th class="weekday">wed</th>
        <th class="weekday">thu</th>
        <th class="weekday">fri</th>
        <th class="weekday">sat</th>

The reason is that in case of ajax requests we are not required to return everything, except the internal calendar content.

Step 2. PHP

The time for action


// Get current year, month and day
list($iNowYear, $iNowMonth, $iNowDay) = explode('-', date('Y-m-d'));
// Get current year and month depending on possible GET parameters
if (isset($_GET['month'])) {
    list($iMonth, $iYear) = explode('-', $_GET['month']);
    $iMonth = (int)$iMonth;
    $iYear = (int)$iYear;
} else {
    list($iMonth, $iYear) = explode('-', date('n-Y'));
// Get name and number of days of specified month
$iTimestamp = mktime(0, 0, 0, $iMonth, $iNowDay, $iYear);
list($sMonthName, $iDaysInMonth) = explode('-', date('F-t', $iTimestamp));
// Get previous year and month
$iPrevYear = $iYear;
$iPrevMonth = $iMonth - 1;
if ($iPrevMonth <= 0) {
    $iPrevMonth = 12; // set to December
// Get next year and month
$iNextYear = $iYear;
$iNextMonth = $iMonth + 1;
if ($iNextMonth > 12) {
    $iNextMonth = 1;
// Get number of days of previous month
$iPrevDaysInMonth = (int)date('t', mktime(0, 0, 0, $iPrevMonth, $iNowDay, $iPrevYear));
// Get numeric representation of the day of the week of the first day of specified (current) month
$iFirstDayDow = (int)date('w', mktime(0, 0, 0, $iMonth, 1, $iYear));
// On what day the previous month begins
$iPrevShowFrom = $iPrevDaysInMonth - $iFirstDayDow + 1;
// If previous month
$bPreviousMonth = ($iFirstDayDow > 0);
// Initial day
$iCurrentDay = ($bPreviousMonth) ? $iPrevShowFrom : 1;
$bNextMonth = false;
$sCalTblRows = '';
// Generate rows for the calendar
for ($i = 0; $i < 6; $i++) { // 6-weeks range
    $sCalTblRows .= '<tr>';
    for ($j = 0; $j < 7; $j++) { // 7 days a week
        $sClass = '';
        if ($iNowYear == $iYear && $iNowMonth == $iMonth && $iNowDay == $iCurrentDay && !$bPreviousMonth && !$bNextMonth) {
            $sClass = 'today';
        } elseif (!$bPreviousMonth && !$bNextMonth) {
            $sClass = 'current';
        $sCalTblRows .= '<td class="'.$sClass.'"><a href="javascript: void(0)">'.$iCurrentDay.'</a></td>';
        // Next day
        if ($bPreviousMonth && $iCurrentDay > $iPrevDaysInMonth) {
            $bPreviousMonth = false;
            $iCurrentDay = 1;
        if (!$bPreviousMonth && !$bNextMonth && $iCurrentDay > $iDaysInMonth) {
            $bNextMonth = true;
            $iCurrentDay = 1;
    $sCalTblRows .= '</tr>';
// Prepare replacement keys and generate the calendar
$aKeys = array(
    '__prev_month__' => "{$iPrevMonth}-{$iPrevYear}",
    '__next_month__' => "{$iNextMonth}-{$iNextYear}",
    '__cal_caption__' => $sMonthName . ', ' . $iYear,
    '__cal_rows__' => $sCalTblRows,
$sCalendarItself = strtr(file_get_contents('templates/calendar.html'), $aKeys);
// AJAX requests - return the calendar
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' && isset($_GET['month'])) {
    header('Content-Type: text/html; charset=utf-8');
    echo $sCalendarItself;
$aVariables = array(
    '__calendar__' => $sCalendarItself,
echo strtr(file_get_contents('templates/index.html'), $aVariables);

I tried to comment on every single line of code in order to let you understand the whole process. In the beginning we make date-related calculations with current date and requested dates. Then, we generate the calendar rows (days), finally, we replace the template keys to values. On Ajax requests, we return only the inner content ($sCalendarItself), otherwise – we display the whole page

Step 3. CSS

At the moment, our calendar does not look properly because it is just a bare html code. Let’s decorate our calendar


/* calendar styles */
#calendar {
    -moz-user-select: none;
    border: 1px solid #EEEEEE;
    border-radius: 6px 6px 6px 6px;
    color: #333333;
    font-family: Arial,sans-serif;
    font-size: 1.1em;
    margin: 10px auto;
    padding: 0.4em;
    width: 90%;
#calendar .navigation {
    background-color: #CC0000;
    border: 1px solid #E3A1A1;
    border-radius: 6px 6px 6px 6px;
    color: #FFFFFF;
    font-weight: bold;
    padding: 1px;
    position: relative;
#calendar .navigation .title {
    background: none repeat scroll 0 0 transparent;
    border-color: rgba(0, 0, 0, 0);
    color: inherit;
    line-height: 1.8em;
    margin: 0 2.3em;
    text-align: center;
#calendar .navigation .prev, #calendar .navigation .next {
    background-image: url(../images/nav.png);
    height: 24px;
    opacity: 0.9;
    position: absolute;
    top: 4px;
    width: 24px;
#calendar .navigation .prev {
    background-position: 0 0;
    left: 4px;
#calendar .navigation .next {
    background-position: -24px 0;
    right: 4px;
#calendar .navigation .prev:hover, #calendar .navigation .next:hover {
    opacity: 1;
#calendar table {
    border-collapse: collapse;
    font-size: 0.9em;
    table-layout: fixed;
    width: 100%;
#calendar table th {
    border: 0 none;
    font-weight: bold;
    padding: 0.7em 0.3em;
    text-align: center;
#calendar table td {
    border: 0 none;
    padding: 1px;
#calendar table td a {
    background-color: #EEEEEE;
    border: 1px solid #D8DCDF;
    color: #004276;
    display: block;
    font-weight: normal;
    opacity: 0.7;
    padding: 0.2em;
    text-align: right;
    text-decoration: none;
#calendar table td a:hover {
    background-color: #F6F6F6;
    border: 1px solid #CDD5DA;
    color: #111111;
#calendar table td.current a {
    font-weight: bold;
    opacity: 1;
#calendar table a {
    background-color: #FBF8EE;
    border: 1px solid #FCD3A1;
    color: #444444;
    font-weight: bold;
    opacity: 1;

Step 4. Images

Only one small image is used in the styles of our calendar: nav.png

PHP AJAX Calendar

Live Demo


download the sources



That’s all for today, we have just prepared stylish responsive calendar. Thanks for your patient attention, and if you really like what we did today – share it with all your friends in your social networks using the form below.


Design Patterns in PHP

0 112075


  1. Hello to everyone, congratz for the post, its a great code.

    I´m from Brazil and the code is in English, i add some code to change the months to portuguese, i hope it helps some one.

    In the Index.php file, after this code :
    // Get name and number of days of specified month
    $iTimestamp = mktime(0, 0, 0, $iMonth, $iNowDay, $iYear);
    list($sMonthName, $iDaysInMonth) = explode('-', date('F-t', $iTimestamp));

    Add this Case

    switch ($sMonthName){
    case "January" :
    $sMonthName = "Janeiro";
    case "February" :
    $sMonthName = "Fevereiro";
    case "March" :
    $sMonthName = "Março";
    case "April" :
    $sMonthName = "Abril";
    case "May" :
    $sMonthName = "Maio";
    case "June" :
    $sMonthName = "Junho";
    case "July" :
    $sMonthName = "Julho";
    case "August" :
    $sMonthName = "Agosto";
    case "September":
    $sMonthName = "Setembro";
    case "October":
    $sMonthName = "Outubro";
    case "November" :
    $sMonthName = "Novembro";
    case "December" :
    $sMonthName = "Dezembro";

    It will change the Month to portuguese.

    Then in calendar.html, change the letter for the day of the week



    In portuguese


    • BRBR always helping, thx very much man, It have made my coding faster and I didnt need to think about, thanks very very much.

    • Hi Vlad,
      This is impossible, especially because we don’t list months at all. We use standard PHP functions to work with dates.

  2. @Vlad, Hey to get the feb month just replace the line
    $iTimestamp = mktime(0, 0, 0, $iMonth, $iNowDay, $iYear);
    $iTimestamp = mktime(0, 0, 0, $iMonth, 1, $iYear);

    This will happen only if you crossed the date 28 as the feb will not have such date.

  3. is it possible to change to something like calendar?(it just shows three days for each click)

  4. Awesome stuff! I come here to freshen up some skills I havent worked on as much, and you have some solid gold.


  5. if $iNowDay = 31. calendar works bad, every month will have 31 day. To fix a bug
    change string
    $iPrevDaysInMonth = (int)date(‘t’, mktime(0, 0, 0, $iPrevMonth, $iNowDay, $iPrevYear));
    $iPrevDaysInMonth = (int)date(‘t’, mktime(0, 0, 0, $iPrevMonth, 1, $iPrevYear));
    $iTimestamp = mktime(0, 0, 0, $iMonth, $iNowDay, $iYear);
    list($sMonthName, $iDaysInMonth) = explode(‘-‘, date(‘F-t’, $iTimestamp));
    $iTimestamp = mktime(0, 0, 0, $iMonth, 1, $iYear);
    list($sMonthName, $iDaysInMonth) = explode(‘-‘, date(‘F-t’, $iTimestamp));
    sorry for my english :)

  6. Hey, hi…

    I am unable to find that nav.png to download from that step 4
    Kindly send that or post it again..

  7. Hello there. Thank you for this tutorial. It was great.
    I would like to ask you something about this. How can I add events to this calendar?

    • Hi Laura, first, you will need to create a new SQL table to store the events. After, you need to create a form where you will add the events. After – you may display events on the calendar (displaying some basic info when you hover your mouse over days of months, or below the calendar)

Leave a Reply