skip to Main Content

I am working on a project where I need to implement a single-row calendar layout, and I have a specific design in mind. I have an image that illustrates the desired result, and I’m struggling to figure out the best approach to achieve this.
Below is result I want
The image shows a calendar with a single row, displaying days horizontally. Each month has its corresponding days, and the layout spans across the screen horizontally. I’m using PHP, and I’m unsure about the best way to structure the HTML and CSS to achieve this responsive and visually appealing layout.

3

Answers


  1. Chosen as BEST ANSWER

    I wanted to share the solution I found for creating a single-row calendar using Owl Carousel, Bootstrap, and jQuery. After experimenting and combining these tools, I was able to achieve a functional and visually appealing calendar design. Here's the approach I took:

    const months = [
            "January",
            "February",
            "March",
            "April",
            "May",
            "June",
            "July",
            "August",
            "September",
            "October",
            "November",
            "December",
          ];
          chooseddate = "";
          const monthShortNames = months.map((month) => month.substring(0, 3));
          const calendarContainer = $("#calendar-container");
          const yearDropdown = $("#yearDropdown");
          const monthDropdown = $("#monthDropdown");
    
          function isTodayOrFuture(year, month, day) {
            const today = new Date();
            const dateToCheck = new Date(year, month, day);
            return dateToCheck >= today;
          }
          const currentYear = new Date().getFullYear();
          const currentMonth = new Date().getMonth();
          const currentDay = new Date().getDate();
    
          function updateMonthDropdownOptions(selectedYear) {
            const monthDropdown = $("#monthDropdown");
            monthDropdown.empty();
    
            for (let month = 0; month < 12; month++) {
              const daysInMonth = new Date(selectedYear, month + 1, 0).getDate();
              if (
                daysInMonth >= new Date().getDate() ||
                selectedYear > currentYear
              ) {
                const option = $("<option>").val(month).text(months[month]);
                monthDropdown.append(option);
              }
            }
            const defaultMonth =
              currentMonth < new Date(selectedYear, 0).getMonth()
                ? currentMonth
                : 0;
            monthDropdown.val(defaultMonth);
          }
    
          function updateCalendar(year, month) {
            calendarContainer.owlCarousel("destroy");
            calendarContainer.empty();
            calendarContainer.owlCarousel({
              loop: false,
              nav: true,
              navText: [
                '<i class="fa-solid fa-chevron-left fa-fw"></i>',
                '<i class="fa-solid fa-chevron-right fa-fw"></i>',
              ],
              margin: 10,
              responsive: {
                0: {
                  items: 1,
                },
                600: {
                  items: 3,
                },
                1000: {
                  items: 6,
                },
              },
              lazyLoad: true,
            });
            const daysInMonth = new Date(year, month + 1, 0).getDate();
            for (let day = 1; day <= daysInMonth; day++) {
              const dateString = `${year}-${(month + 1)
                .toString()
                .padStart(2, "0")}-${day.toString().padStart(2, "0")}`;
              
              if (
                isTodayOrFuture(year, month, day) ||
                (year === currentYear &&
                  month === currentMonth &&
                  day === currentDay)
              ) {
                const dayCard = $("<div>")
                  .addClass("day-card card rounded")
                  .html(
                    "<p class='fw-bold'>" +
                      getDayOfWeek(year, month, day) +
                      "</p>" +
                      "<h3>" +
                      day +
                      "</h3>" +
                      "<p>" +
                      monthShortNames[month] +
                      "</p>"
                  )
                  .css("cursor", "pointer")
                  .data("date", dateString);
    
                dayCard.on("click", function () {
                    calendarContainer
                      .find(".day-card")
                      .removeClass("border-success selectedcard");
                    const clickedDate = $(this).data("date");
                    console.log("Clicked on", clickedDate);
                    chooseddate = clickedDate;
                    $(this).addClass("border-success selectedcard");
                });
                calendarContainer.trigger("add.owl.carousel", [dayCard]);
              }
            }
            calendarContainer.trigger("refresh.owl.carousel");
          }
          yearDropdown.val(currentYear);
          updateMonthDropdownOptions(currentYear);
          updateCalendar(currentYear, currentMonth);
    
          yearDropdown.on("change", function () {
            const selectedYear = parseInt($(this).val(), 10);
            const selectedMonth = parseInt(monthDropdown.val(), 10);
            updateMonthDropdownOptions(selectedYear);
            updateCalendar(selectedYear, selectedMonth);
          });
    
          monthDropdown.on("change", function () {
            const selectedMonth = parseInt($(this).val(), 10);
            const selectedYear = parseInt(yearDropdown.val(), 10);
            updateCalendar(selectedYear, selectedMonth);
          });
    
          function getDayOfWeek(year, month, day) {
            const date = new Date(year, month, day);
            const daysOfWeek = [
              "Sunday",
              "Monday",
              "Tuesday",
              "Wednesday",
              "Thursday",
              "Friday",
              "Saturday",
            ];
            return daysOfWeek[date.getDay()];
          }
    <link href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.theme.default.min.css" rel="stylesheet"/>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/assets/owl.carousel.min.css" rel="stylesheet"/>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/owl.carousel.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <div class="row w-100 m-auto mb-1 text-center">
          <div class="col-md-4 mb-2">
            <select class="form-control" id="yearDropdown">
              <option value="">Select Year</option>
              <option value="2023" selected>2023</option>
              <option value="2024">2024</option>
              <option value="2025">2025</option>
            </select>
          </div>
          <div class="col-md-4 mb-2">
            <select class="form-control" id="monthDropdown">
              <option value="0">January</option>
              <option value="1">February</option>
              <option value="2">March</option>
              <option value="3">April</option>
              <option value="4">May</option>
              <option value="5">June</option>
              <option value="6">July</option>
              <option value="7">August</option>
              <option value="8">September</option>
              <option value="9">October</option>
              <option value="10">November</option>
              <option value="11">December</option>
            </select>
          </div>
          <div class="col-md-12 mt-1">
            <div class="owl-carousel" id="calendar-container"></div>
          </div>
        </div>


  2. The HTML and CSS are fairly simple, obviously tweak to your exact needs.

    ol.calendar {
      display: flex;
      flex-wrap: nowrap;
      flex-direction: row;
      overflow-x: auto;
      padding-bottom: 2em;
      gap: 0.5em;
      li {
        flex: 0 0 7em;
        display: block;
        padding: 0.25em;
        border: solid #aaa 1px;
        border-radius: 7px;
        text-align: center;
        div {
          &:nth-child(1) {
            letter-spacing: -0.04em;
          }
          &:nth-child(2) {
            font-size: 2em;
            font-weight: 800;
          }
        }
      }
    }
    <ol class="calendar">
    
      <li>
        <div>FRIDAY</div>
        <div>1</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>SATURDAY</div>
        <div>2</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>SUNDAY</div>
        <div>3</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>MONDAY</div>
        <div>4</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>TUESDAY</div>
        <div>5</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>WEDNESDAY</div>
        <div>6</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>THURSDAY</div>
        <div>7</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>FRIDAY</div>
        <div>8</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>SATURDAY</div>
        <div>9</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>SUNDAY</div>
        <div>10</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>MONDAY</div>
        <div>11</div>
        <div>DEC</div>
      </li>
    
      <li>
        <div>TUESDAY</div>
        <div>12</div>
        <div>DEC</div>
      </li>
    
    </ol>

    To be honest, you wouldn’t need to use ol and li either, they can all be div if you want – I use ol/li since semantically it is an ordered list with list items :p

    Or, and since you’ve tagged javascript but haven’t tagged php, here’s some javascript to create the whole calendar – this time without <ol>/<li>

    It’s a little more convoluted than it needs to be, simply to allow multiple months :p

    function makeCalendar(year, month) {
      const frag = document.createDocumentFragment();
      const months = document.querySelector('.months');
      const month_template = document.querySelector('#month-template');
      const clone = month_template.content.cloneNode(true);
      frag.append(clone)
      const tgt = frag.firstElementChild;
      const template = document.querySelector('#day-template');
      const date = new Date(year, month - 1, 1);
      while(date.getMonth() === month - 1) {
        const parts = date
          .toLocaleDateString(undefined, {weekday:"long", month:"short", day:"numeric"})
          .split(/,? /)
          .map(s => s.toUpperCase());
        const clone = template.content.cloneNode(true);
        clone.querySelectorAll(".day > div").forEach((el, index) => el.textContent = parts[index]);
        tgt.appendChild(clone);
        date.setDate(date.getDate() + 1);
      }
      months.append(frag);
    }
    makeCalendar(2023, 11); // code takes one away from month
    makeCalendar(2023, 12); // code takes one away from month
    .months .month {
      display: flex;
      flex-wrap: nowrap;
      flex-direction: row;
      gap: 0.5em;
      overflow-x: auto;
      padding-block: 2em;
      .day {
        flex: 0 0 7em;
        padding: 0.25em;
        border: solid #aaa 1px;
        border-radius: 7px;
        text-align: center;
        .dow {
          letter-spacing: -0.04em;
        }
        .date {
          font-size: 2em;
          font-weight: 800;
        }
      }
    }
    <div class="months">
    </div>
    
    <template id="month-template">
      <div class="month">
      </div>
    </template>
    
    <template id="day-template">
      <div class="day">
        <div class="dow"></div>
        <div class="date"></div>
        <div></div>
      </div>
    </template>
    Login or Signup to reply.
  3. HereĀ“s another one as a template to start with. The function gives you exact weekdays and daynumbers to a month:

    <?php
    
    function dates_month($month, $year)
    {
        $num = cal_days_in_month(CAL_GREGORIAN, $month, $year);
        $dates_month = array();
    
        for ($i = 1; $i <= $num; $i++) {
            $mktime = mktime(0, 0, 0, $month, $i, $year);
            $dates_month[$i]['weekday'] = date("D", $mktime);
            $dates_month[$i]['day'] = date("d", $mktime);
            $dates_month[$i]['month'] = date("M", $mktime);
        }
    
        return $dates_month;
    }
    
    $currentRow = dates_month(12, 2023);
    ?>
    
    <!DOCTYPE html>
    <html>
    
    <head>
        <title></title>
        <style>
    
            .boxes {
                display: flex;
                flex-direction: row nowrap;
                justify-items: left;
                font-family: Arial, Helvetica, sans-serif;
                font-weight: bold;
            }
    
            .box {
                flex: 0 0 70px;
                border: 1px solid black;
                border-radius: 10px;
                display: flex;
                flex-direction: column;
                justify-content: center;
                margin-right: 20px;
                text-align: center;
                height: 100px;
            }
    
        </style>
    </head>
    
    <body>
        <div class="boxes">
            <?php
            foreach ($currentRow as $currentDay) {
            ?>
                <div class="box">
                    <div class="weekday"><?= $currentDay['weekday']; ?></div>
                    <div class="day"><?= $currentDay['day']; ?></div>
                    <div class="month"><?= $currentDay['month']; ?></div>
                </div>
            <?php
            }
            ?>
        </div>
    </body>
    
    </html>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search