Tutorial - How to Style An Event Calendar in Drupal 7Tutorial - How to Style An Event Calendar in Drupal 7

Categories:

Now that Drupal 7 has a decent track record and updated modules, there are more things you can do every day. Recent changes to the Calendar module make building and styling your own calendar better than ever. Whether you run a site for small community functions or you are full-fledged event coordinator, a useful calendar will make your site that much better.

Today we'll be going through a basic setup and styling process for Calendar in Drupal 7. Let's take a look at what we'll be building:

Calendar

As you can see, we have a nice styled calendar instead of the default styling. We have categorized events with color coded bars at the top as well as a few stylistic tweaks.

1. Module installation & setup:

You know what they say: no use retelling what has already been told. I'll be using Calendar 3.x, Views, and Date API. I had issues with the recommended alpha release of Calendar module (namely the taxonomy based color coding) so for purposes of this tutorial I am actually going to use a dev build (7.x-3.x-dev from Nov 19). Fortunately, Arlin Sandbulte has put together a really nice video about how to go about setting up your event and calendar up with Views. For purposes of this post I am going to assume you have watched the video: check it out here. When that is done you should have an event content type and calendar set up. I am going to use the Month view for styling.

There are a few additional things we're going to have to set up at this point. The first of which is adding a taxonomy to our event nodes. We'll use this to provide categorization for our calendar legend. I'm going to add 3 or 4 categories. I highly recommend setting this up even if you don't think you will need them. In the future if you ever need it you won't have to relearn or go back and try to peel open your code. We're going to be doing everything up front.

Event types

After that let's hop back to our Views settings for the calendar view. Go to "Format" and Calendar Items Settings. Here we have an awesome legend feature built right in. Choose stripes based on taxonomy and select your term field name. If you have Color module enabled you can simply click and select your legend colors (otherwise input the CSS hex values).

Row style options

We also need to add our event taxonomy to the fields within Views. In my case I added "Content: Event Type." Make sure you exclude this field from the actual display because we already have a color code and we don't need the term indicated twice. Lastly what we need is to add our legend. You can either create a block and add it manually, but I actually prefer to use the View interface to add a footer directly in my View. As you might guess, this is done under "Footer" where you add a global text area.

Footer

Note that the "&#9632" character is simply a square. I'm using span to color the squares the same as I selected in the Calendar item settings. I also wrap the legend in a div so that I can style it later.


2. Themeing and Styling:

Let's go over how a calendar views renders the HTML for styling. Like most other Views, the calendar has numerous wrapper and helper classes. Our Views footer will also have its own wrapper. The tricky part comes with the calendar itself, which is rendered as a table. More importantly, cells are not rendered as boxes as whole days. In order to be able to display multi-day events, Views actually renders multiple rows within and single week and then places 7 columns within those rows (one for each day). That means that some weeks that contain more than 1 event will contain more rows than other weeks. This makes some styling options impossible (like having a background image cover an entire day cell). Check out the following diagram that illustrates how this works:

Week rows

As you can see, you have to think ahead about how you are going to style the day cells. Our options are pretty limited but we'll try out some visual tricks to do what we can. Also, you can only style the cell borders on one side, meaning you can't do any 1 pixel light / 1 pixel dark borders to make things look recessed.

At any rate, let's start with some overall tweaks. Depending on your theme setup you may want to leave these alone or customize these elements. I am going to add a bit of a margin on the top of the View, add a wood texture to the background, and add a box shadow to the calendar table. Also, just as a note I am going to strictly use CSS3 declarations when needed. For true cross-browser support you will have to use the Webkit and Mozilla equivalents as well. For IE you can use CCS3Pie.

 

.view-calendar {
margin-top:20px;
}
.view-calendar .view-content {
background:url(../images/wood-bg.jpg);
padding-bottom:20px;
}
.calendar-calendar {
margin-left:20px;
width:890px;
padding-top:20px;
}
.calendar-calendar .month-view {
box-shadow:0 0 10px #000000;
}

 
The default header places the previous and next tabs on the right side of the View. I'm going to move them to be on the left and right with the title in the middle. Doing this means tweaking and overwriting a lot of default styles. I also am going to give the pagers an image background to up the quality factor, add a gradient background, and round the top corners.

 

.view .date-nav-wrapper .date-nav {
color:#cccccc;
background:url(../images/cal-header.png);
border-radius:8px 8px 0 0;
padding:20px;
width:890px;
text-shadow:1px 1px 0px #000000;
margin:0;
}
.view .date-nav-wrapper .date-prev {
float:left;
position:relative;
right:0;
text-align:right;
width:80px;
background:url(../images/prev.png);
padding:5px 15px 5px 0;
width:85px;
height:20px;
}
.view .date-nav-wrapper .date-next {
float:right;
position:relative;
right:0;
text-align:left;
width:80px;
background:url(../images/next.png);
padding:5px 0 5px 15px;
width:85px;
height:20px;
}
.view .date-nav-wrapper .date-heading {
float:left;
width:650px;
}

 
When all is said and done it should look something like this:

Header

Now on to the calendar table. The table header contains the day text. I'm going to have to again undo some default styling and then augment it with a nice opaque background.

 

.calendar-calendar thead tr {
background:none;
}
.calendar-calendar th.days {
background:#000000;
opacity:0.3;
border:none;
padding:5px 0;
color:#ffffff;
}

 
Let's hit up the footer really quick, just 2 simple declarations to extend my wood background and style the legend. Here I have to use the RGBA property so that my text doesn't become opaque with the background:

.view-calendar .view-footer {
background:url(../images/wood-bg.jpg);
padding:0 20px 20px 20px;
font-size:0.8em;
}
.view-calendar .view-footer #legend {
color:#aaaaaa;
background-color:rgba(0, 0, 0, 0.3);
line-height:3em;
width:350px;
padding-left:10px;
float:right;
}

 
It should look like this:

Footer

For the cells I'm going to have to do quite a bit of finessing. All of the borders need to be changed on the columns. Different column types have different classes so those will need to be targeted as well. For the spacer cell I am going to actually use a gradient background. Lastly, the default styles are a bit squished for my taste, so I will add a min-height to the empty columns.

 

.calendar-calendar td {
border:1px solid #dadada;
border-right-color:#dadada;
border-bottom-color:#e3e3e3;
}
.calendar-calendar td.empty {
border-color:#dadada;
color:#dadada;
}
.calendar-calendar .month-view .full td.date-box.today,
.calendar-calendar .month-view .full tr td.multi-day.ends-today,
.calendar-calendar .month-view .full tr td.single-day.today {
border-color:#999999;
}
td.single-day {
background:url(../images/cell-bg.png) bottom repeat-x;
}
td.single-day .inner {
min-height:50px;
}

 
Lastly, we need to hit the events. Numerous column classes necessitate a few lengthy declarations. The basic idea is that I am going to round off the corners, add a slight gradient, and override a few default styles to tweak things to my liking.

 

.calendar-calendar .month-view .full td.multi-day div.monthview,
.calendar-calendar .week-view .full td.multi-day div.weekview,
.calendar-calendar .day-view .full td.multi-day div.dayview,
.calendar-calendar .month-view .full td.multi-day .inner .monthview .continues,
.calendar-calendar .month-view .full td.multi-day .inner .monthview .cutoff,
.calendar-calendar .week-view .full td.multi-day .inner .weekview .continues,
.calendar-calendar .week-view .full td.multi-day .inner .weekview .cutoff {
background:url(../images/event-bg.png) bottom repeat-x;
border-radius:10px;
}
.calendar-calendar .month-view .full td.multi-day .calendar.monthview .contents,
.calendar-calendar .week-view .full td.multi-day .calendar.weekview .contents {
top:2px;
}
.calendar-calendar .item {
color:#333333;
}
.calendar-calendar .item a {
color:#333333;
text-shadow:1px 1px 0px #ffffff;
}
.calendar-calendar .item .continues {
color:#333333;
}

 
Here's a detail shot of what we should have at the end:

Detail

That should do it. Views actually provides 6 different styles of calendars, so you might want to think about more detailed schedule calendars or perhaps even block calendars. Even though we had to use a dev version module, it is very usable and I haven't run into any errors myself. As always, let us know if you found this tutorial useful or suggest ideas for future articles!

Need a Custom Designed Theme?

If you need a custom designed theme for your business then our designers can work with you to create a unique concept that is consistent with your brand, clearly communicates your value proposition and helps you achieve your goals. >> Click here to contact us and let us know about your needs and we'll analyze and provide you with an estimate for designing and development your custom theme.