← Back toCSS grid

Create an event calendar

Written byPhuoc Nguyen
24 Dec, 2023
event calendar
Here's what we'll cover:
  • Learn how to define the number and size of columns and rows using the `grid-template-columns` and `grid-template-rows` properties.
  • Discover how to position an item precisely using the `grid-column` and `grid-row` properties.

An event calendar is a handy tool that helps you manage and schedule upcoming events. It's beneficial for individuals, organizations, and businesses alike, allowing you to keep track of important dates and deadlines. You can use it to schedule meetings, appointments, social gatherings, holidays, project deadlines, and much more. By using an event calendar, you can visualize your upcoming schedule and plan accordingly to ensure you never miss an important engagement or deadline.
In this post, we'll show you how to create an event calendar using CSS grid. So, let's get started!

HTML markup

To create an event calendar using CSS grid, we'll need to start with the HTML markup. In the code snippet below, you'll see that we've created a container div with a class of `calendar`. Inside this container, there are seven child `div`s with a class of `calendar__weekday` representing each day of the week. Additionally, there are `div`s with a class of `calendar__day` representing each day of the month.
<div class="calendar">
<div class="calendar__weekday">Sun</div>
<div class="calendar__weekday">Mon</div>
<div class="calendar__weekday">Tue</div>
<div class="calendar__weekday">Wed</div>
<div class="calendar__weekday">Thu</div>
<div class="calendar__weekday">Fri</div>
<div class="calendar__weekday">Sat</div>

<!-- Week 1 -->
<div class="calendar__day">29</div>
<div class="calendar__day">30</div>
<div class="calendar__day">31</div>
<div class="calendar__day">1</div>
<div class="calendar__day">2</div>
<div class="calendar__day">3</div>
<div class="calendar__day">4</div>

<!-- Repeat with the remaining weeks ... -->
The `.calendar` CSS class styles the container div that holds all of the calendar elements. By setting the display property to `grid`, we can use CSS Grid layout on the container. To define the number and size of columns and rows in our grid, we use the `grid-template-columns` and `grid-template-rows` properties.
In this example, we create 7 columns each with a width of 1 fraction unit by using `repeat(7, 1fr)` for `grid-template-columns`. Each row has a height of 5rem, except for the first row which is only 2rem tall. This gives us a grid with 7 columns and 6 rows, where each cell represents one day in the calendar.
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: 2rem repeat(5, 5rem);
Here is what the calendar looks like:

Adding borders between the cells

Adding borders between cells in an event calendar is crucial. It makes it easier to read and visually separates each day. Without borders, it can be tough to distinguish one day from another, especially when there are multiple events scheduled on the same day. Borders create a clear hierarchy, making it easy to see where one day ends and another begins. Plus, it gives the calendar a professional look.
To add borders to our event calendar, we can use CSS `border` properties. We apply a 1px solid border to the left, top, and right sides of the whole calendar using the `border-left`, `border-top`, and `border-right` properties, respectively.
.calendar {
border-left: 1px solid rgb(203 213 225);
border-top: 1px solid rgb(203 213 225);
border-right: 1px solid rgb(203 213 225);
We're also adding a 1-pixel solid border to the bottom of each weekday element by using the `border-bottom` property.
.calendar__weekday {
border-bottom: 1px solid rgb(203 213 225);
Lastly, we add a 1px solid border to the bottom and right sides of each day by utilizing the `border-bottom` and `border-right` properties, respectively.
.calendar__day {
border-bottom: 1px solid rgb(203 213 225);
border-right: 1px solid rgb(203 213 225);
To remove the border on the right side of every seventh day, which is Saturday, we can use the CSS pseudo-class `:nth-child(7n + 7)` and set its `border-right` property to 0. This simple trick ensures that Saturday's cell doesn't have an unnecessary border on its right side.
.calendar__day:nth-child(7n + 7) {
border-right: 0;
Take a look at the demo below. It's worth noting that we moved the day number to the right of the corresponding cell to free up space on the left for events.

Adding events to the calendar

We're almost there! Let's finish up the calendar by adding some events. To do this, we simply place the events at the end of the calendar element. Check out the sample code below, where we've added an event to the calendar.
<div class="calendar">
<!-- Weekdays ... -->

<!-- Days ... -->

<!-- Events -->
<div style="grid-column: 2 / 5; grid-row: 2; margin-top: 2rem">Metting</div>
To position events on a calendar, we use the `grid-column` and `grid-row` properties. These properties help us specify where an element should start and end within a grid container. In the example above, we added an event `div` with a style attribute that sets its `grid-column` property to `2 / 5` and its `grid-row` property to `2`. This means that the event will span three columns (from column 2 to column 4) and one row (row 2). By adjusting these values, we can position events anywhere on the calendar grid. Additionally, we added a margin to the top of the event `div` to give it some space from the top border of its cell.
Although it sounds good in theory, the layout is currently broken, as you can see in this demo.
We've added an event to our calendar, but it's causing some problems. The event takes up three columns, which means the days after the first column get pushed to the next columns. This could become a bigger problem if we add more events.
To solve this issue, we need to explicitly position each day cell in the calendar. We can do this using the `nth-child` selector in CSS, which matches every nth child element of its parent. We use this selector to target every seventh `.calendar__day` element and assign a different grid column to each one. By doing this, we ensure that events don't mess up the layout of the days.
We use the `7n+1` formula in CSS to target every first child of each week. This means that the first column of each week will always represent the dates from Sunday, keeping our calendar layout consistent across weeks.
.calendar__day:nth-child(7n + 1) {
grid-column: 1;
To select the day cells for the second row of our calendar grid, we can use the `nth-child` selector with the `n+8` and `-n+14` formulas. This may sound complicated, but it's actually quite simple.
The `n+8` formula selects every element starting at position 8, while the `-n+14` formula selects every element up to position 14, counting backwards from the last element in the container. Together, they allow us to target all the `.calendar__day` elements that fall between the 8th and 14th position within their parent container.
Once we've targeted these elements, we assign them to `grid-row: 2` to ensure they appear in the second row of our calendar layout. This keeps them below the weekday labels in the first row but above any events that may be added to the calendar.
.calendar__day:nth-child(n + 8):nth-child(-n + 14) {
grid-row: 2;
Here are the other CSS styles that explicitly position the cells using the `nth-child` selector. By combining these styles with CSS grid and formulas, we can create a stable event calendar. This means we can add and remove events without worrying about the layout of other elements on the page.
.calendar__day:nth-child(7n + 2) {
grid-column: 2;
.calendar__day:nth-child(7n + 3) {
grid-column: 3;
.calendar__day:nth-child(7n + 4) {
grid-column: 4;
.calendar__day:nth-child(7n + 5) {
grid-column: 5;
.calendar__day:nth-child(7n + 6) {
grid-column: 6;
.calendar__day:nth-child(7n + 7) {
grid-column: 7;

.calendar__day:nth-child(n + 15):nth-child(-n + 21) {
grid-row: 3;
.calendar__day:nth-child(n + 22):nth-child(-n + 28) {
grid-row: 4;
.calendar__day:nth-child(n + 29):nth-child(-n + 35) {
grid-row: 5;
.calendar__day:nth-child(n + 36):nth-child(-n + 42) {
grid-row: 6;

Resolving overlapping events

If we have multiple events positioned in the same row, you may notice that they overlap, causing visual clutter and making it difficult to distinguish between them.
To address this issue, we can use the `margin-top` property to create space between events. By adjusting the `margin-top` value for each event, we can ensure that they are properly spaced apart and do not overlap.
For example, if two events are in the same row, adding a larger `margin-top` value to one of them will create more space between them. This will ensure that both events are visible and easily distinguishable.
<div style="grid-column: 2 / 6; grid-row: 3; margin-top: 2rem">Design</div>
<div style="grid-column: 3 / 8; grid-row: 3; margin-top: 4rem">Implementation</div>
In the example above, we added a `margin-top` value of `2rem` to the first event and `4rem` to the second event. This simple trick ensures that there is enough space between events and prevents them from overlapping with each other.
By combining the `margin-top` property with CSS grid, we can create an event calendar that is both stable and visually appealing. This makes it easy to read and understand events at a glance.
Check out the final demo to see the results for yourself!


In summary, we've learned how to create a simple and effective event calendar using CSS grid. By using the `grid-template-columns` and `grid-template-rows` properties, we can create a grid calendar and define the number and size of columns and rows.
We've also explored how to style the calendar using CSS borders and pseudo-classes, and how to position events within the grid using the `grid-column` and `grid-row` properties. To avoid event overlap, we adjusted the `margin-top` property for each event.
By following these steps, you can create your own event calendar that is both functional and visually appealing. With some additional customization, you can further enhance your calendar's design and functionality to meet your specific needs.
If you found this post helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

Questions? 🙋

Do you have any questions about front-end development? If so, feel free to create a new issue on GitHub using the button below. I'm happy to help with any topic you'd like to learn more about, even beyond what's covered in this post.
While I have a long list of upcoming topics, I'm always eager to prioritize your questions and ideas for future content. Let's learn and grow together! Sharing knowledge is the best way to elevate ourselves 🥷.
Ask me questions

Recent posts ⚡

Newsletter 🔔

If you're into front-end technologies and you want to see more of the content I'm creating, then you might want to consider subscribing to my newsletter.
By subscribing, you'll be the first to know about new articles, products, and exclusive promotions.
Don't worry, I won't spam you. And if you ever change your mind, you can unsubscribe at any time.
Phước Nguyễn