Calendar Component

Readonly Calendar

A readonly calendar has cells containing static text or hypertext.

The current date is conveyed using calendar__cell--current and clipped text.

August 2023
SuMoTuWeThFrSa
12345
6789101112
1314 - today1516171819
20212223242526
2728293031
<div class="calendar">
  <div class="calendar__body">
    <div class="calendar__month">
      <table>
        <caption>
          August 2019
        </caption>
        <thead>
          <tr>
            <th>Su</th>
            <th>Mo</th>
            <th>Tu</th>
            <th>We</th>
            <th>Th</th>
            <th>Fr</th>
            <th>Sa</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td colspan="2" />
            <td>
              <span> 1 </span>
            </td>
            <td>
              <span> 2 </span>
            </td>
            <td>
              <span> 3 </span>
            </td>
            <td>
              <span> 4 </span>
            </td>
            <td>
              <span> 5 </span>
            </td>
          </tr>
          <tr>
            <td>
              <span> 6 </span>
            </td>
            <td>
              <span> 7 </span>
            </td>
            <td>
              <span> 8 </span>
            </td>
            <td>
              <span> 9 </span>
            </td>
            <td>
              <span> 10 </span>
            </td>
            <td>
              <span> 11 </span>
            </td>
            <td>
              <span> 12 </span>
            </td>
          </tr>
          <tr>
            <td>
              <span> 13 </span>
            </td>
            <td>
              <span class="calendar__cell--current">
                14
                <span class="clipped"> - today </span>
              </span>
            </td>
            <td>
              <span> 15 </span>
            </td>
            <td>
              <span> 16 </span>
            </td>
            <td>
              <span> 17 </span>
            </td>
            <td>
              <span> 18 </span>
            </td>
            <td>
              <span> 19 </span>
            </td>
          </tr>
          <tr>
            <td>
              <a href="https://www.ebay.com"> 20 </a>
            </td>
            <td>
              <span> 21 </span>
            </td>
            <td>
              <span> 22 </span>
            </td>
            <td>
              <span> 23 </span>
            </td>
            <td>
              <span> 24 </span>
            </td>
            <td>
              <span> 25 </span>
            </td>
            <td>
              <span> 26 </span>
            </td>
          </tr>
          <tr>
            <td>
              <a href="https://www.ebay.com"> 27 </a>
            </td>
            <td>
              <span> 28 </span>
            </td>
            <td>
              <a href="https://www.ebay.com"> 29 </a>
            </td>
            <td>
              <span> 30 </span>
            </td>
            <td>
              <span> 31 </span>
            </td>
            <td colspan="2" />
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

NOTE: for the eagle-eyed BEM afionados, we are saying each span has an implicit class of calendar__cell .

Read-Only Calendar with Inactive Dates

Inactive/unavailable dates are conveyed using calendar__cell--disabled and offscreen text.

August 2023
SuMoTuWeThFrSa
1 - inactive2 - inactive3 - inactive4 - inactive5 - inactive
6 - inactive7 - inactive8 - inactive9 - inactive10 - inactive11 - inactive12 - inactive
13 - inactive14 - today1516171819
20212223242526
2728293031
<div class="calendar">
  <div class="calendar__body">
    <div class="calendar__month">
      <table>
        <caption>
          August 2023
        </caption>
        <thead>
          <tr>
            <th>Su</th>
            <th>Mo</th>
            <th>Tu</th>
            <th>We</th>
            <th>Th</th>
            <th>Fr</th>
            <th>Sa</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td colspan="2" />
            <td>
              <span class="calendar__cell--disabled">
                1
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                2
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                3
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                4
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                5
                <span class="clipped"> - inactive </span>
              </span>
            </td>
          </tr>
          <tr>
            <td>
              <span class="calendar__cell--disabled">
                6
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                7
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                8
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                9
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                10
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                11
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                12
                <span class="clipped"> - inactive </span>
              </span>
            </td>
          </tr>
          <tr>
            <td>
              <span class="calendar__cell--disabled">
                13
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--current">
                14
                <span class="clipped"> - today </span>
              </span>
            </td>
            <td>
              <span> 15 </span>
            </td>
            <td>
              <span> 16 </span>
            </td>
            <td>
              <span> 17 </span>
            </td>
            <td>
              <span> 18 </span>
            </td>
            <td>
              <span> 19 </span>
            </td>
          </tr>
          <tr>
            <td>
              <a href="https://www.ebay.com"> 20 </a>
            </td>
            <td>
              <span> 21 </span>
            </td>
            <td>
              <span> 22 </span>
            </td>
            <td>
              <span> 23 </span>
            </td>
            <td>
              <span> 24 </span>
            </td>
            <td>
              <span> 25 </span>
            </td>
            <td>
              <span> 26 </span>
            </td>
          </tr>
          <tr>
            <td>
              <a href="https://www.ebay.com"> 27 </a>
            </td>
            <td>
              <span> 28 </span>
            </td>
            <td>
              <a href="https://www.ebay.com"> 29 </a>
            </td>
            <td>
              <span> 30 </span>
            </td>
            <td>
              <span> 31 </span>
            </td>
            <td colspan="2" />
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

Read-Only Calendar with Date Range

Date ranges are conveyed using calendar__cell--selected , calendar__range , calendar__range--start , calendar__range-end and clipped text.

August 2023
SuMoTuWeThFrSa
1 - inactive2 - inactive3 - inactive4 - inactive5 - inactive
6 - inactive7 - inactive8 - inactive9 - inactive10 - inactive11 - inactive12 - inactive
13 - inactive14 - today151617 - start of range18 - in range19 - in range
20 - in range21 - in range22 - in range23 - in range24 - in range25 - end of range26
2728293031
<div class="calendar">
  <div class="calendar__body">
    <div class="calendar__month">
      <table>
        <caption>
          August 2023
        </caption>
        <thead>
          <tr>
            <th>Su</th>
            <th>Mo</th>
            <th>Tu</th>
            <th>We</th>
            <th>Th</th>
            <th>Fr</th>
            <th>Sa</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td colspan="2" />
            <td>
              <span class="calendar__cell--disabled">
                1
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                2
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                3
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                4
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                5
                <span class="clipped"> - inactive </span>
              </span>
            </td>
          </tr>
          <tr>
            <td>
              <span class="calendar__cell--disabled">
                6
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                7
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                8
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                9
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                10
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                11
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--disabled">
                12
                <span class="clipped"> - inactive </span>
              </span>
            </td>
          </tr>
          <tr>
            <td>
              <span class="calendar__cell--disabled">
                13
                <span class="clipped"> - inactive </span>
              </span>
            </td>
            <td>
              <span class="calendar__cell--current">
                14
                <span class="clipped"> - today </span>
              </span>
            </td>
            <td>
              <span> 15 </span>
            </td>
            <td>
              <span> 16 </span>
            </td>
            <td
              class="calendar__cell--selected calendar__range calendar__range--start"
            >
              <span>
                17
                <span class="clipped"> - selected - start of range </span>
              </span>
            </td>
            <td class="calendar__range">
              <span>
                18
                <span class="clipped"> - in range </span>
              </span>
            </td>
            <td class="calendar__range">
              <span>
                19
                <span class="clipped"> - in range </span>
              </span>
            </td>
          </tr>
          <tr>
            <td class="calendar__range">
              <a href="#">
                20
                <span class="clipped"> - in range </span>
              </a>
            </td>
            <td class="calendar__range">
              <span>
                21
                <span class="clipped"> - in range </span>
              </span>
            </td>
            <td class="calendar__range">
              <span>
                22
                <span class="clipped"> - in range </span>
              </span>
            </td>
            <td class="calendar__range">
              <span>
                23
                <span class="clipped"> - in range </span>
              </span>
            </td>
            <td class="calendar__range">
              <span>
                24
                <span class="clipped"> - in range </span>
              </span>
            </td>
            <td
              class="calendar__cell--selected calendar__range calendar__range--end"
            >
              <span>
                25
                <span class="clipped"> - selected - end of range </span>
              </span>
            </td>
            <td>
              <span> 26 </span>
            </td>
          </tr>
          <tr>
            <td>
              <a href="https://www.ebay.com"> 27 </a>
            </td>
            <td>
              <span> 28 </span>
            </td>
            <td>
              <a href="https://www.ebay.com"> 29 </a>
            </td>
            <td>
              <span> 30 </span>
            </td>
            <td>
              <span> 31 </span>
            </td>
            <td colspan="2" />
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

Interactive Calendar

An interactive calendar uses toggle buttons to allow the input of single dates or date ranges.

NOTE: a fully functional and accessible interactive calendar requires JavaScript and is outside the scope of a CSS library such as eBay Skin. The examples below are NOT fully functional and serve to demonstrate the necessary HTML semantics and styling hooks only.

Interactive Calendar With Single Date Selection

A single date selection is conveyed using aria-pressed .

NOTE: in comparison to the readonly calendar, with buttons we can now leverage the disabled property and aria-current instead of clipped text.

August 2023
SuMoTuWeThFrSa
<div class="calendar">
  <div class="calendar__body">
    <div class="calendar__month">
      <table>
        <caption>
          August 2023
        </caption>
        <thead>
          <tr>
            <th>Su</th>
            <th>Mo</th>
            <th>Tu</th>
            <th>We</th>
            <th>Th</th>
            <th>Fr</th>
            <th>Sa</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td colspan="2" />
            <td>
              <button disabled>1</button>
            </td>
            <td>
              <button disabled>2</button>
            </td>
            <td>
              <button disabled>3</button>
            </td>
            <td>
              <button disabled>4</button>
            </td>
            <td>
              <button disabled>5</button>
            </td>
          </tr>
          <tr>
            <td>
              <button disabled>6</button>
            </td>
            <td>
              <button disabled>7</button>
            </td>
            <td>
              <button disabled>8</button>
            </td>
            <td>
              <button disabled>9</button>
            </td>
            <td>
              <button disabled>10</button>
            </td>
            <td>
              <button disabled>11</button>
            </td>
            <td>
              <button disabled>12</button>
            </td>
          </tr>
          <tr>
            <td>
              <button disabled>13</button>
            </td>
            <td>
              <button aria-current="date">14</button>
            </td>
            <td>
              <button>15</button>
            </td>
            <td>
              <button>16</button>
            </td>
            <td class="calendar__cell--selected">
              <button aria-pressed="true">17</button>
            </td>
            <td>
              <button>18</button>
            </td>
            <td>
              <button>19</button>
            </td>
          </tr>
          <tr>
            <td>
              <button>20</button>
            </td>
            <td>
              <button>21</button>
            </td>
            <td>
              <button>22</button>
            </td>
            <td>
              <button>23</button>
            </td>
            <td>
              <button>24</button>
            </td>
            <td>
              <button>25</button>
            </td>
            <td>
              <button>26</button>
            </td>
          </tr>
          <tr>
            <td>
              <button>27</button>
            </td>
            <td>
              <button>28</button>
            </td>
            <td>
              <button>29</button>
            </td>
            <td>
              <button>30</button>
            </td>
            <td>
              <button>31</button>
            </td>
            <td colspan="2" />
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

Interactive Calendar With Date Range Selection

Date ranges are bookended by two buttons with the aria-pressed property. All buttons in between these dates leverage clipped text for assistive technology.

August 2023
SuMoTuWeThFrSa
<div class="calendar">
  <div class="calendar__body">
    <div class="calendar__month">
      <table>
        <caption>
          August 2023
        </caption>
        <thead>
          <tr>
            <th>Su</th>
            <th>Mo</th>
            <th>Tu</th>
            <th>We</th>
            <th>Th</th>
            <th>Fr</th>
            <th>Sa</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td colspan="2" />
            <td>
              <button disabled>1</button>
            </td>
            <td>
              <button disabled>2</button>
            </td>
            <td>
              <button disabled>3</button>
            </td>
            <td>
              <button disabled>4</button>
            </td>
            <td>
              <button disabled>5</button>
            </td>
          </tr>
          <tr>
            <td>
              <button disabled>6</button>
            </td>
            <td>
              <button disabled>7</button>
            </td>
            <td>
              <button disabled>8</button>
            </td>
            <td>
              <button disabled>9</button>
            </td>
            <td>
              <button disabled>10</button>
            </td>
            <td>
              <button disabled>11</button>
            </td>
            <td>
              <button disabled>12</button>
            </td>
          </tr>
          <tr>
            <td>
              <button disabled>13</button>
            </td>
            <td>
              <button aria-current="date">14</button>
            </td>
            <td>
              <button>15</button>
            </td>
            <td>
              <button>16</button>
            </td>
            <td
              class="calendar__cell--selected calendar__range calendar__range--start"
            >
              <button aria-label="17 - start of range" aria-pressed="true">
                17
              </button>
            </td>
            <td class="calendar__range">
              <button aria-label="18 - in range">18</button>
            </td>
            <td class="calendar__range">
              <button aria-label="19 - in range">19</button>
            </td>
          </tr>
          <tr>
            <td class="calendar__range">
              <button aria-label="20 - in range">20</button>
            </td>
            <td class="calendar__range">
              <button aria-label="21 - in range">21</button>
            </td>
            <td class="calendar__range">
              <button aria-label="22 - in range">22</button>
            </td>
            <td class="calendar__range">
              <button aria-label="23 - in range">23</button>
            </td>
            <td class="calendar__range">
              <button aria-label="24 - in range">24</button>
            </td>
            <td
              class="calendar__cell--selected calendar__range calendar__range--end"
            >
              <button aria-label="25 - end of range" aria-pressed="true">
                25
              </button>
            </td>
            <td>
              <button>26</button>
            </td>
          </tr>
          <tr>
            <td>
              <button>27</button>
            </td>
            <td>
              <button>28</button>
            </td>
            <td>
              <button>29</button>
            </td>
            <td>
              <button>30</button>
            </td>
            <td>
              <button>31</button>
            </td>
            <td colspan="2" />
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</div>

Calendar With Header Pagination

The calendar module allows an optional header section for pagination between months.

August 2023

August 2023
SuMoTuWeThFrSa
12345
6789101112
1314 - today1516171819
20212223242526
2728293031
<div class="calendar">
  <div class="calendar__header">
    <div class="calendar__header--inner">
      <button
        class="icon-btn icon-btn--small icon-btn--transparent"
        aria-label="Previous Month - July 2023"
      >
        <svg aria-hidden="true" class="icon icon--24">
          <use href="#icon-chevron-left-24" />
        </svg>
      </button>
      <h3>August 2023</h3>
      <button
        class="icon-btn icon-btn--small icon-btn--transparent"
        aria-label="Next Month - September 2023"
      >
        <svg aria-hidden="true" class="icon icon--24">
          <use href="#icon-chevron-right-24" />
        </svg>
      </button>
    </div>
  </div>
  <div class="calendar__body">
    <div class="calendar__month">
      <!-- readonly or interactive table goes here -->
    </div>
  </div>
</div>

Multi-month Calendar with Header Pagination

Multiple instances of calendar__month can be rendered inside of the calendar__body .

July 2023

August 2023

September 2023

July 2023
SuMoTuWeThFrSa
1
2345678
9101112131415
16171819202122
23242526272829
3031
August 2023
SuMoTuWeThFrSa
12345
6789101112
1314 - today1516171819
20212223242526
2728293031
September 2023
SuMoTuWeThFrSa
12
3456789
10111213141516
17181920212223
24252627282930
<div class="calendar">
  <div class="calendar__header">
    <div class="calendar__header--inner">
      <button
        class="icon-btn icon-btn--small icon-btn--transparent"
        aria-label="Previous Month - July 2019"
      >
        <svg aria-hidden="true" class="icon icon--24">
          <use href="#icon-chevron-left-24" />
        </svg>
      </button>
      <h3>July 2023</h3>
      <h3>August 2023</h3>
      <h3>September 2023</h3>
      <button
        class="icon-btn icon-btn--small icon-btn--transparent"
        aria-label="Next Month - November 2019"
      >
        <svg aria-hidden="true" class="icon icon--24">
          <use href="#icon-chevron-right-24" />
        </svg>
      </button>
    </div>
  </div>
  <div class="calendar__body">
    <div class="calendar__month">
      <!-- readonly or interactive table goes here -->
    </div>
    <div class="calendar__month">
      <!-- readonly or interactive table goes here -->
    </div>
    <div class="calendar__month">
      <!-- readonly or interactive table goes here -->
    </div>
  </div>
</div>