---
title: "JQuery Calendar Custom Day Cells Example | Mobiscroll"
component: "Calendar"
framework: "jQuery"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/jquery/calendar/activity-calendar"
---

# Custom Day Cells - jQuery Calendar demo

Render activity rings, availability indicators, or per-day metrics inside each day cell of an inline JQuery calendar date picker. For jQuery or jQuery Mobile.

- [Live demo](https://demo.mobiscroll.com/jquery/calendar/activity-calendar)
- [View code on GitHub](https://github.com/acidb/mobiscroll-demos-jquery/tree/main/src/demos/datepicker/calendar/activity-calendar)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/calendar/activity-calendar.md), [Angular](https://demo.mobiscroll.com/angular/calendar/activity-calendar.md), [React](https://demo.mobiscroll.com/react/calendar/activity-calendar.md), [Vue](https://demo.mobiscroll.com/vue/calendar/activity-calendar.md)

## Description

Add custom content to the day cells of the calendar. This can be dynamic content based on the date like an activity tracker that uses daily move data from an array of records.

Use the [`renderDayContent`](https://mobiscroll.com/docs/jquery/datepicker/api#renderer-renderDayContent) function to return custom markup that will be used when the day cells are being rendered.

## What this demo shows

- Shows an inline monthly date picker example with custom day cell for selecting a single date.
- **Inline date picker** Embeds a monthly date picker directly in the page without an input by using the inline display mode.
- **Header navigation** Opens the month and year picker from the label in the upper-left corner. The blue previous and next arrow buttons on the right navigate between months.
- **Month view** Displays a fixed weekday header with abbreviated day names from Sunday through Saturday and arranges the dates in a grid below it.
- **Month navigation** Changes the displayed month when the user clicks and drags the calendar left or right.
- **Day cell states** Highlights a day number with a gray background on hover and a blue background on selection. The current date is highlighted by default and remains blue when another date is selected.
- **Custom day content** Displays an activity indicator below each date using daily move data from an array of records, demonstrating how day cells can render dynamic content based on the date.
- **Adjacent months** Shows dates from the previous and next months in a muted style. Selecting one navigates the calendar to the corresponding month.

## Best for

- **Activity tracking** Showing daily progress, exercise totals, completed habits, or other date-based metrics directly in the calendar.
- **Availability calendars** Indicating available, limited, or unavailable dates before the user makes a selection.
- **Booking and pricing** Displaying daily prices, promotions, capacity, or booking status alongside each date.
- **Deadlines and milestones** Marking due dates, project milestones, or days with scheduled work in a compact monthly view.
- **Operational monitoring** Surfacing daily counts, status indicators, or exceptions so users can identify dates that need attention.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/jquery/datepicker/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/jquery/datepicker/api#opt-themeVariant) - option
- [`controls`](https://mobiscroll.com/docs/jquery/datepicker/api#opt-controls) - option
- [`touchUi`](https://mobiscroll.com/docs/jquery/datepicker/api#opt-touchUi) - option
- [`display`](https://mobiscroll.com/docs/jquery/datepicker/api#opt-display) - option
- [`renderDayContent`](https://mobiscroll.com/docs/jquery/datepicker/api#renderer-renderDayContent) - renderer

## Code

### JS

```js
mobiscroll.setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

$(function () {
  var activities = [
    {
      date: '2026-10-16T00:00',
      move: 200,
      exercise: 360,
      stand: 180,
    },
    {
      date: '2026-10-17T00:00',
      move: 360,
      exercise: 150,
      stand: 230,
    },
    {
      date: '2026-10-18T00:00',
      move: 180,
      exercise: 200,
      stand: 280,
    },
    {
      date: '2026-10-19T00:00',
      move: 120,
      exercise: 150,
      stand: 200,
    },
    {
      date: '2026-10-20T00:00',
      move: 320,
      exercise: 180,
      stand: 100,
    },
    {
      date: '2026-10-21T00:00',
      move: 120,
      exercise: 100,
      stand: 200,
    },
    {
      date: '2026-10-22T00:00',
      move: 230,
      exercise: 170,
      stand: 330,
    },
    {
      date: '2026-10-23T00:00',
      move: 320,
      exercise: 260,
      stand: 80,
    },
    {
      date: '2026-10-24T00:00',
      move: 200,
      exercise: 140,
      stand: 180,
    },
    {
      date: '2026-10-25T00:00',
      move: 360,
      exercise: 300,
      stand: 160,
    },
    {
      date: '2026-10-26T00:00',
      move: 80,
      exercise: 360,
      stand: 360,
    },
    {
      date: '2026-10-27T00:00',
      move: 220,
      exercise: 170,
      stand: 290,
    },
    {
      date: '2026-10-28T00:00',
      move: 120,
      exercise: 40,
      stand: 100,
    },
    {
      date: '2026-10-29T00:00',
      move: 120,
      exercise: 200,
      stand: 80,
    },
  ];

  $('#demo-activity-calendar')
    .mobiscroll()
    .datepicker({
      controls: ['calendar'],
      touchUi: true,
      display: 'inline',
      renderDayContent: function (args) {
        var a = activities.find(function (obj) {
          return +new Date(obj.date) === +args.date;
        });

        function getDeg(nr) {
          return {
            rotate1: nr > 180 ? 180 : nr,
            rotate2: nr > 180 ? nr - 180 : 0,
          };
        }

        function getStyle(rotate) {
          return ' style="transform: rotateZ(' + rotate + 'deg)"';
        }

        return (
          '<div class="screen">' +
          '<div class="' +
          (a ? 'dial move' : '') +
          '">' +
          '<div class="dial-background"' +
          (a ? ' style="background:#752a2a"' : '') +
          '></div>' +
          '<div class="dial-container container1">' +
          '<div class="wedge"' +
          (a ? getStyle(getDeg(a.move).rotate1) : '') +
          '></div>' +
          '</div>' +
          '<div class="dial-container container2">' +
          '<div class="wedge"' +
          (a ? getStyle(getDeg(a.move).rotate2) : '') +
          '></div>' +
          '</div>' +
          '<div class="marker start"></div>' +
          '<div class="marker end"' +
          (a ? getStyle(a.move) : '') +
          '></div>' +
          '</div>' +
          '<div class="' +
          (a ? 'dial exercise' : '') +
          '">' +
          '<div class="dial-background"' +
          (a ? ' style="background:#4a6915"' : '') +
          '></div>' +
          '<div class="dial-container container1">' +
          '<div class="wedge"' +
          (a ? getStyle(getDeg(a.exercise).rotate1) : '') +
          '></div>' +
          '</div>' +
          '<div class="dial-container container2">' +
          '<div class="wedge"' +
          (a ? getStyle(getDeg(a.exercise).rotate2) : '') +
          '></div>' +
          '</div>' +
          '<div class="marker start"></div>' +
          '<div class="marker end"' +
          (a ? getStyle(a.exercise) : '') +
          '></div>' +
          '</div>' +
          '<div class="' +
          (a ? 'dial stand' : '') +
          '">' +
          '<div class="dial-background"' +
          (a ? ' style="background:#157b76"' : '') +
          '></div>' +
          '<div class="dial-container container1">' +
          '<div class="wedge"' +
          (a ? getStyle(getDeg(a.stand).rotate1) : '') +
          '></div>' +
          '</div>' +
          '<div class="dial-container container2">' +
          '<div class="wedge"' +
          (a ? getStyle(getDeg(a.stand).rotate2) : '') +
          '></div>' +
          '</div>' +
          '<div class="marker start"></div>' +
          '<div class="marker end"' +
          (a ? getStyle(a.stand) : '') +
          '></div>' +
          '</div>' +
          '</div>'
        );
      },
    });
});
```

### HTML

```html
<div id="demo-activity-calendar"></div>
```

### CSS

```css
.screen {
    position: relative;
    width: 2em;
    height: 2em;
    margin: 5px auto 10px auto;
}

.screen * {
    box-sizing: content-box;
}

.screen .dials {
    width: 1em;
    height: 1em;
    border-radius: 50%;
    position: absolute;
    top: 0.875em;
    left: 0;
}

.screen .dial {
    border: 1px solid #000;
    border-radius: 50%;
}

/**** DIAL 1 ****/

.dial.move {
    position: absolute;
    width: 2em;
    height: 2em;
}

.dial.move::before {
    content: "";
    width: 0.75em;
    height: 0.75em;
    position: absolute;
    top: -0.29em;
    left: calc(50% - 0.1875em);
    z-index: 10;
}

.dial.move::after {
    content: "";
    background: #000;
    border-radius: 50%;
    width: 1.5em;
    height: 1.5em;
    position: absolute;
    top: 0.25em;
    left: 0.25em;
}

.dial.move .dial-container {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1em;
    overflow: hidden;
}

.dial.move .wedge {
    width: 1em;
    height: 2em;
    position: absolute;
    top: 0;
    left: 0;
}

.dial.move .container1 {
    left: 1em;
}

.dial.move .container1 .wedge {
    border-radius: 2em 0 0 2em;
    background: #fc1d20;
    left: -1em;
    transform-origin: 100% 50%;
}

.dial.move .container2 {
    left: 0;
}

.dial.move .container2 .wedge {
    background: #fc1d20;
    border-radius: 0 2em 2em 0;
    transform-origin: 0 50%;
    left: 1em;
}

.dial.move .marker {
    width: 0.25em;
    height: 0.25em;
    background: #fc1d20;
    border-radius: 50%;
    position: absolute;
    top: 0;
    left: calc(50% - 0.125em);
}

.dial.move .end {
    transform-origin: 50% 1em;
}

/**** DIAL 2 ****/

.dial.exercise {
    position: absolute;
    width: 1.5em;
    height: 1.5em;
    top: 0.25em;
    left: 0.25em;
}

.dial.exercise::before {
    content: "";
    width: 0.75em;
    height: 0.75em;
    position: absolute;
    top: -0.29em;
    left: calc(50% - 0.1875em);
    z-index: 10;
}

.dial.exercise::after {
    content: "";
    background: #000;
    border-radius: 50%;
    width: 1em;
    height: 1em;
    position: absolute;
    top: 0.25em;
    left: 0.25em;
}

.dial.exercise .dial-container {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 0.75em;
    overflow: hidden;
}

.dial.exercise .wedge {
    border-radius: 50%;
    width: 0.75em;
    height: 1.5em;
    position: absolute;
}

.dial.exercise .container1 {
    left: 0.75em;
}

.dial.exercise .container1 .wedge {
    border-radius: 2em 0 0 2em;
    position: absolute;
    background: #9cfc33;
    left: -0.75em;
    transform-origin: 100% 50%;
}

.dial.exercise .container2 {
    left: 0;
}

.dial.exercise .container2 .wedge {
    background: #9cfc33;
    border-radius: 0 2em 2em 0;
    transform-origin: 0 50%;
    left: .75em;
}

.dial.exercise .marker {
    width: 0.25em;
    height: 0.25em;
    background: #9cfc33;
    border-radius: 50%;
    position: absolute;
    top: 0;
    left: calc(50% - 0.125em);
}

.dial.exercise .end {
    transform-origin: 45% 0.75em;
}

/**** DIAL 3 ****/

.dial.stand {
    position: absolute;
    width: 1em;
    height: 1em;
    top: 0.5em;
    left: 0.5em;
}

.dial.stand::before {
    content: "";
    width: 0.75em;
    height: 0.75em;
    position: absolute;
    top: -0.24em;
    left: calc(50% - 0.1875em);
    z-index: 10;
}

.dial.stand::after {
    content: "";
    background: #000;
    border-radius: 50%;
    width: 0.5em;
    height: 0.5em;
    position: absolute;
    top: 0.25em;
    left: 0.25em;
}

.dial.stand .dial-container {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1em;
    overflow: hidden;
}

.dial.stand .wedge {
    border-radius: 50%;
    width: 0.5em;
    height: 1em;
    position: absolute;
}

.dial.stand .container1 {
    left: 0.5em;
}

.dial.stand .container1 .wedge {
    position: absolute;
    background: #32cbd4;
    border-radius: 2em 0 0 2em;
    left: -0.5em;
    transform-origin: 100% 50%;
}

.dial.stand .container2 {
    left: 0;
}

.dial.stand .container2 .wedge {
    background: #32cbd4;
    border-radius: 0 2em 2em 0;
    transform-origin: 0 50%;
    left: 0.5em;
}

.dial.stand .marker {
    width: 0.25em;
    height: 0.25em;
    background: #32cbd4;
    border-radius: 50%;
    position: absolute;
    top: 0;
    left: calc(50% - .125em);
}

.dial.stand .end {
    transform-origin: 50% .5em;
}

.dial-background {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    border-radius: 50%;
}
```

## Implementation notes

- Use `controls: ['calendar']`, `display: 'inline'`, and `touchUi` set to `true`.
- React/JS/jQuery: pass `renderDayContent`, a function returning custom markup to inject below/around each day number. Angular: use the `dayContentTemplate` option (an `ng-template` bound with a template reference variable). Vue: use the `#dayContent` slot.
- Inside the renderer, look up the activity/metric value for the rendered day's date from a local data array (matching by date) and render the custom indicator (concentric activity rings, built from plain `div`s with inline `transform`/`background` styles) alongside the default day number - the renderer does not replace the day number itself, only adds to the cell.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-jquery.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config jquery
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config jquery --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/jquery/getting-started/installation

## Related demos

- Previous: [Appointment Booking](https://demo.mobiscroll.com/jquery/calendar/appointment-booking.md) - Build booking date selection interfaces with an inline JQuery calendar — show per-day prices and disable fully booked dates for appointment flows.
