From our sponsor: Ready to show your plugin skills? Enter the Penpot Plugins Contest (Nov 15-Dec 15) to win cash prizes!
Today we want to share a flexible calendar concept with you. Calendars can be a very tricky thing when it comes to their layout and responsiveness. This is an experiment for trying out some grid layouts that can be applied to calendars. We’ve created a jQuery plugin for the calendar itself and you can see some examples of how to use it in the demos. The aim is to provide a suitable layout for both, small and big screens and keeping the calendar structure fluid when possible. On large screens we want to show a grid-based layout while on smaller screens, we want to simply stack the days of the month.
Please note that the demos will only work as intended in browsers that support the new CSS properties used here, especially calc().
The calendar designs are based on these two beauties found on Dribbble:
- Day – the most beautiful calendar app for your iPhone by Toby Negele
- Calendar by Tomas Gajar
For the calendar plugin to work, we simply need a container with the class “fc-calendar-container”:
<div id="calendar" class="fc-calendar-container"></div>
The plugin can be called like this:
$( '#calendar' ).calendario();
The plugin will create a calendar with the following structure:
<div id="calendar" class="fc-calendar-container"> <div class="fc-calendar fc-five-rows"> <div class="fc-head"> <div>Monday</div> <div>Tuesday</div> <div>Wednesday</div> <div>Thursday</div> <div>Friday</div> <div>Saturday</div> <div>Sunday</div> </div> <div class="fc-body"> <div class="fc-row"> <div></div> <div></div> <div></div> <div><span class="fc-date">1</span><span class="fc-weekday">Thu</span></div> <div><span class="fc-date">2</span><span class="fc-weekday">Fri</span></div> <div><span class="fc-date">3</span><span class="fc-weekday">Sat</span></div> <div><span class="fc-date">4</span><span class="fc-weekday">Sun</span></div> </div> <div class="fc-row"> <!-- ... --> </div> <div class="fc-row"> <!-- ... --> </div> <div class="fc-row"> <!-- ... --> </div> <!-- ... --> </div> </div> </div>
The calendar will consist of a head for the listing of the weekdays and a body with rows for the days of the month. Each “cell” will contain the date and weekday (if applicable) and we control the height of the rows by setting the right class to the container (four, five or six rows). The styling for the default calendar is defined in calendar.css.
Note that a cell that contains some content/event will look as follows:
<div class="fc-content"> <span class="fc-date">14</span> <span class="fc-weekday">Wed</span> <div> <!-- Some event/content --> </div> </div>
Note that the weekday of each cell is hidden by default because we have the calendar head with the weekdays. The ones in the cell are especially for the case when we apply media queries to reset the layout of the calendar to be stacked vertically. Here we will want to show the weekdays for each day.
It’s clear that a calendar could/should be represented by a table, but due to some table rendering differences between the browsers (especially IE9), we chose not to use it. You can of course adjust the plugin to output a table, though.
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
The important part of making the calendar grid fluid is the styling of the row and the div (or the “cell”):
.fc-four-rows .fc-row { height: 25%; } .fc-five-rows .fc-row { height: 20%; } .fc-six-rows .fc-row { height: 16.66%; height: -moz-calc(100%/6); height: -webkit-calc(100%/6); height: calc(100%/6); } .fc-calendar .fc-row > div, .fc-calendar .fc-head > div { float: left; height: 100%; width: 14.28%; /* 100% / 7 */ width: -moz-calc(100%/7); width: -webkit-calc(100%/7); width: calc(100%/7); position: relative; }
So, we define different heights depending on the amount of rows we’ll have, using calc() where we know that the result is not a round number. For the inner div we will set the width to be 100 divided by 7.
Options
The following (default) options are available:
// initialize calendar with this month (1-12). Default is today month : null, // initialize calendar with this year. Default is today year : null, // initial data/content for the calendar // format: // { // 'MM-DD-YYYY' : 'HTML Content', // 'MM-DD-YYYY' : 'HTML Content', // 'MM-DD-YYYY' : 'HTML Content' // ... // } caldata : null, weeks : [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ], weekabbrs : [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ], months : [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ], monthabbrs : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ], // choose between values in options.weeks or options.weekabbrs displayWeekAbbr : false, // choose between values in options.months or options.monthabbrs displayMonthAbbr : false, // left-most day in the calendar // 0 - Sunday, 1 - Monday, ... , 6 - Saturday startIn : 1, // callback function for when clicking on a day cell in the calendar // $el is the cell // $content is the content division of the cell // dateProperties is an object with the following properties: // day : day number, // month : month number from 1 - 12, // monthname : name from options.months, // year : year number, // weekday : week number from 0 - 6, // weekdayname : name from options.weeks onDayClick : function( $el, $content, dateProperties ) { return false; }
The following public methods are available:
// return the year that is currently being viewed getYear() // return the month that is currently being viewed (1-12) getMonth() // returns the name of the month that is currently being viewed getMonthName() // returns the content division inside the cell associated to day "day" getCell( day ) // sets the data to the calendar. Merges the contents of the passed caldata with the one already set (if any) setData( caldata ) // shows the calendar for today's month and year // month is from 1-12 gotoNow( callback ) // shows the calendar for month "month" and year "year" // month is from 1-12 goto( month, year, callback ) // goes back one month in the calendar gotoPreviousMonth( callback ) // goes back one year in the calendar gotoPreviousYear( callback ) // goes further one month in the calendar gotoNextMonth( callback ) // goes further one year in the calendar gotoNextYear( callback )
You can use setData to add content to the calendar. You can see examples for that in the demo files.
The basic styling is defined in the calendar.css file and you can see examples of how to modify the calendar style and add to it in the custom CSS files.
Demos
Check out the demos:
Demo 2 Great !!
really like it :))
Great job Mary! 🙂 both demos look great!
Nicely done!
Love it love it love it and I SO need it! Thank you Manoela!
Super awesome article!
Both dribbble links are leading to the same shot, by the way 😉
Thanks! Links are fixed now! Cheers, ML
Thanks everybody, glad you like it! Cheers, ML
Kewl calendar!! I’m only missing keyboard navigation there.
Would be really nice to navigate with arrows to switch monthes.
very nice calendar, perfect to my clients!!
thanks!!
Great work as always ( potente mesmo Mary Lou 🙂 )
Keyboard navigation would be a great Plus
Awesome article. You are really talented Mary, and one of the best web designer/deveoper i’ve ever seen.
Keep doing good job, i eagerly waiting for your next article.
I love this calendar, but it’s rendering strangely in IE10 Preview. Sometimes the left borders on days are missing, the days on the far right are too wide and the last days of the month are running outside the calendar container. I took a screenshot and it’s here: http://www.screencast.com/t/BTmqi75mgh
To add to this, it looks like IE10 is calculating the width of each day correctly, but is wrapping the week at six days, so Sunday is going onto another line, which leaves each week with six days and tacks on another row at the bottom, which overflows the container.
Huh, weirder yet, this only seems to happen when I have the IE10 window maximized. If I don’t have it maximized and stretch the window horizontally so it is as wide as if it were full screen, everything looks great.
Great. Love the first one although I would suggest making the font for the links in the calendar date a bit bolder for better visibility 🙂
This is an amazing plugin. I had a question; does the user have to manually input each event or does this sync with a google cal / etc?
Not working for me with 2013 data
Hi Fernando, what exactly does not work for you? You can see an example of an event that I’ve added to the demos (1st of January 2013, make sure to clean your browser cache) and it works fine. Let me know, cheers, ML
Ok, now working… Sorry, just a little trouble with aptana… I think. Thank you so much, an amazing plugin…
thanks for sharing !
Nice demo.
I prefer keyboard navigation tools
i am having issues in the “mobile version”.
if i load straightly the page :
http://www.zingari.eu/mobi/cal/cal.html
it works
else from
http://www.zingari.eu/mobi/
it continues the loader… in an infinite loop..
any hints is appreciated ty.
Open the console, you have js errors.. Hope it helps. Cheers, ML
By The Way , Codrops Rocks ! RockDrops !
Ty For the EverAlwaysDaily Inspiration MaryLou !
Regards, Ichtyo .
WTF IS THAT? VERY NICE TUTO!!!!
Two demos look so Nice:)!
Fantastic. I wish I had half your creativity. Great work…
Great work….. was very helpful !!!1
Very great plugin! So nice!!
Hi Mary Lou! This is amazing plugin!!! Congratulations! I like so much! In this plugin when you mouse-over on the div which gives the description can be enlarged rather than leading to a link? Thank you!!
Great script.
Any plans to move this over to Github for further development? I think that would be awesome.
Hi Banago, you missed the GitHub link in the end of the article 🙂 Cheers, ML
Mary, that’s awesome! Thanks!
this is great work, love the design on demo one. thanks
how to pull the data from an ics/ical file and display it with this nice and flexible style?
Is it possible to attach a SQL or MySQL database to the calendar? as I want to manage the calendar entries and this seems to be the most logical fashion of managing the entries.
something wrong with your _getBody logic .fc-today is getting added to previous days in last month. quick fix I did
var cellClasses = today && inner!==” ? ‘fc-today ‘ : ”;
nevermind I’m retarded. this works better I think
today = this.month === this.today.getMonth() && this.year === this.today.getFullYear() && day === this.today.getDate() && this.startingDay === j,
nope that doesn’t work either lol. the ‘today’ logic needs tweaking
Very nice but not working on this f……. IE….
How I add more than 1 event in a day?
It doesn’t work with 2013. With these data in data.js
var codropsEvents = { '12-25-2012' : 'Natale', '12-31-2012' : 'Capodanno' };
it works. But with these data
var codropsEvents = { '12-25-2012' : 'Natale', '12-31-2012' : 'Capodanno' '01-06-2013' : 'Befana' };
no calendar is displayed, jut the calendar title. Tried with Safari, Chrome and FF latest versions… Any clue?
It misses a comma after ‘Capodanno’. Maybe that’s the problem? Cheers, ML
Nice Calendar. I am having issues getting it to display today’s date. Am I missing a setting somewhere?
Looks great both on desktop and mobile devices.
I’m trying to not display empty cells on mobile devices, because it saves space and the cells with events in it are the essential ones.
I’ll post my results here when I manage it.
Okay, I made it really complicated and wanted to do it with jQuery.
My solution is CSS, since the cells with an event have a class the other ones don’t have (.fc-content’).
Also I thought it makes sense to display the current day so you can see how much time’s left until the next event.
Put this in your stylesheet:
@media screen and (max-width: 880px) , screen and (max-height: 450px) {
.fc-calendar .fc-row > div {
display: none;
}
.fc-calendar .fc-row > div.fc-content,
.fc-calendar .fc-row > div.fc-today {
display: block;
}
}
Nevertheless an option to not render empty cells at all would be nice.
Hi,
Great Calendar !!! I just have a little problem with the CSS. I tried to put the calendar on my website but this CSS part
*,
*:after,
*:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
margin: 0;
is breaking my website. I don’t find how to replace this part…
Sorry forget my question… I was tired and didn’t think to the easiest way… juste had to replace * with .container *…
Love the plugin, a fantastic tool for a responsive site that I am developing however is there an easy way of hooking up gcal.js to display Google events?
Thanks
Dan
how to add new items or new entries using dynamic way?
It’s awesome ! I have a question : I filled the data.js dynamically, no problem for it but the calendar shows me one event while I have two, how can i do to have two events ?
Oh u rocks ! 😀
Fannyny,
How have you added events dynamically? I need to do this….
Thanks
Dan
I’m also curious as to how you filled data.js dynamically. I’m not having any luck.
Tranks for this Great Plugin.
Just wrote a tutorial how to connect the CMS Processwire to it.
To find here: http://processwire.com/talk/topic/2435-tutorial-howto-create-a-simple-eventcalendar/
These may be dumb questions as I only have a little experience with javascript.
1. On Demo 1, when I shrink my browser, it changes to a list type format. I would like to make that permanent so it doesn’t display in calendar format. How do I do that?
2. In the format in question 1, can you tell it to only display dates with events?
Hi Matt,
The style sheet has a media query to tell the div’s(days) to change from calendar format to list format when the browser/device goes below a certain width so just remove the media query and all relating normal CSS so it always displays this way.
Not sure on your second question :/ Sorry!
Dan
Dan,
I cannot locate a div with the id “days” in any of the provided css style sheets. Would you please be able to assist me further? Thank you.
Matt,
I am assuming you have a knowledge of css and can inspect website elements using Google Chrome or Firefox.
So looking at Demo 1 the class you need to be looking at is “.fc-calendar .fc-row > div”, you will be able to see that when the browser width is below 800px the styles for this class change, all you need to do is locate these styles in this media query, “@media screen and (max-width: 880px) , screen and (max-height: 450px)” and make this class your default by overwriting the base styles for this class, I would recommend you comment out the old styles in case you wanted to re-instate that the class at some point in the future.
Hope that helps.
Dan
Awesome work hats off
Wonderful plugin, Nice to use for a booking component for example. Keep up the good work.
Hi! I love this design..but i have a question.
When i load the html/css/js, the calendar only loads dates from monday-saturday, do you know why? Also, the widget that makes the event pop up on January 1st, does not work.
Also is there a way to resize the entire calendar?
Thanks!
If I have few events in the same day like:
var codropsEvents = {
’01-02-2013′ : ‘ev1′,
’01-02-2013’ : ‘ev2’
};
it`s just showing me the last one, how could i fix this?
Beside this minor thing it`s a great plugin to use!
If you would like to display multiple events at the same date, let’s say:
’01-01-2013′ : ‘New Year’s Day‘,
’01-01-2013’ : ‘<a href="Christmas holidays‘
You should simply put one event after another like this:
’01-01-2013’ : ‘New Year’s Day<a href="Christmas holidays‘
Calendario will then display them as two events on the same date
Wonderful plugin and I have just found a use case for it. massive thanks !
Hi there! I’m wondering about a weekly view of this awesome calendar.. thanks!
Thats right. Overview of Weeks/Month would be great. Ideas, Anybody?!
If the cells can’t expand to fit the necessary data (say, three events in one day), it’s not much use…
I was wondering exactly the same thing, isn’t there a workaround to make the rows expand to fit the necessary data?
Since I removed the “white-space: nowrap” line to show the full events, I would like the rows to expand to fit the events. I tried a lot of different things in the css file, but nothing seems to work.
Hey its awesome calendar i have ever seen. I’m in big mess. In your example you put all events in javascript file “data.js”. Here I’m loading data from database using jsp page and set jsp page to
contentType="text/javascript"
but its not working. Need your help ASAPSorry It was my mistake in placing date format like
15-02-2013
but the actual format id02-14-2013
Hi, As list only for weeks ?
Hi there!
any idea to show events on hover only ??
Looking forward to reading you or I’ll edit your plugin otherwise…
It’s okay!
I did it using this snippet
$('.fc-date').hover(function () { $(this).parents('.fc-content').find('div').show(); //alert($(this).parents('.fc-row').html()); }, function () { // $(this).parents('.fc-content').find('div').hide(); });
Where do you place this snippet specifically?