I need the calendar to be flexible and responsive. It need to work for all thinkable screen sizes. Today it looks really odd as the buttons are floating over the year and if some dates are inside the calendar it may overflows the screen size and other stuff. This has major usability issues, see below:

I'm myself currently not sure how to solve this with day thead's, but maybe some brainstorming can help finding the way to go.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

KarenS’s picture

I have some responsive css that I haven't had time to finish up.

The idea I started working with was adding the following css, which should make the calendar collapse down into a list in a small window:


@media all and (max-width: 959px) {
  .calendar-calendar .month-view table.full {
    position: relative; 
  }
  .calendar-calendar .month-view .full tr td {
    width: 100%;
    float: left;
    text-align: left;
  }
  .calendar-calendar .month-view .full tr td.single-day:before { 
    content: attr(data-day-of-month); 
    font-weight: bold;
  }
  .calendar-calendar .month-view .full thead tr,
  .calendar-calendar .month-view .full tr th.days,
  .calendar-calendar .month-view .full tr td.date-box,
  .calendar-calendar .month-view .full tr td.no-entry,
  .calendar-calendar .month-view .full tr td.empty {
    display: none;
  }
}

I haven't had time to get back to this idea.

stephen Piscura’s picture

Forgive me as this may be obvious, but is this something that should exist within the module itself or at the theme level?

hass’s picture

Well... That's not so easy to answer. On one side it's theme level, but on the other side if the module code does not work it can be overridden. We are on the way to make all core themes responsible with D8. Therefore i think it should be part of module code. The yaml theme as example is flexible and responsive for very many years, but today it becomes more and more standard. The max-width may be discussable...

I hope i can try karens example code by the end of this week.

hass’s picture

#1 looks very useful to me. I wondered first why you remove all empty days, but that's perfect on mobiles with limited display space. I hope to find some time soon to solve the button and year display issues. I just think the (max-width: 959px) may be too large value, but it works nevertheless.

Thank you very much for sharing this!

hass’s picture

I'm sharing my latest version now. It aligns the centered month name to the left and also adds the full day name to the column. It only becomes a problem after the CSS is compressed as the CSS compressor in core has a followup bug #1686178: CSS compressor destroys valid css "content" attribute values here as it removes the space in ", ". I've added a Unicode workaround below.

@media screen and ( max-width: 740px ) {
  .view .date-nav-wrapper .date-heading {
    text-align: left;
  }
  .calendar-calendar .month-view table.full {
    position: relative; 
  }
  .calendar-calendar .month-view .full tr td {
    width: 100%;
    float: left;
    text-align: left;
  }
  .calendar-calendar tbody tr:hover td {
    background: none;
  }
  .calendar-calendar .month-view .full tr.single-day {
    border-top: 1px solid #ccc;
  }
  .calendar-calendar .month-view .full tr td.single-day:before { 
    content: attr(data-day-of-month) ",\0000a0" attr(headers); 
    font-weight: bold;
  }
  .calendar-calendar .month-view .full thead tr,
  .calendar-calendar .month-view .full tr th.days,
  .calendar-calendar .month-view .full tr td.date-box,
  .calendar-calendar .month-view .full tr td.no-entry,
  .calendar-calendar .month-view .full tr td.empty {
    display: none;
  }
}
acranius’s picture

Thanks for sharing!
Works great, but if there are multi-day events in your calendar, the day (start date) is not displayed.
I'm trying to figure out how to solve that.

acranius’s picture

One possible solution is to set the "Multi-day style" option in the calendar settings to "Display multi-day item as a single column".
Contra:
1. Obviously, you can't display them as a multiple column row.
2. When the calendar is displayed as a list, there are three lines for a three day event, like:

  • 27. Thursday
  • 3 Day Event
  • 28. Thursday
  • 3 Day Event
  • 29. Thursday
  • 3 Day Event

It would be better if you had just one line, like:

  • 27.-29
  • 3 Day Event

But that's no CSS problem.

jonjonz’s picture

Bump!
Any further developments regarding the responsive design?

:-)

tmsimont’s picture

I've been neck deep in calendar code lately and was wondering the same about responsive design. I think a big problem with RD and calendar is the fact that calendar depends on tables. Tables are hard to bend into new shapes with CSS. I think you'd need to use a new type of div-based style plugin so you could really play with the appearance.

I recently built a table-like div view that collapses on mobile devices:
http://www.kenyaschoolreport.com/schools/find-school/results?s=location&...

I think you'd need something similar for calendar. It's a standard table-like grid in large windows, but it collapses to a list format on small devices.

I will probably start working on this in the near future as I need a responsive calendar. I've been talking to myself on this issue #1908018: Break up large functions of calendar_plugin_style into smaller functions for a while, which could be a first step in breaking down the calendar plugin to something that could be extended into new style plugins.

stephen Piscura’s picture

Here's a great example of a responsive calendar:

http://www.atlantaballet.com/calendar/

Albeit a really different approach in its markup.

stephen Piscura’s picture

Also, an example using Drupal Calendar can be found here:

http://www.stlouissabres.com/calendar/month/2012-10

Referenced from: http://groups.drupal.org/node/266223

tmsimont’s picture

thanks stephen good stuff. do you know if atlanta ballet is using some kind of open source plugin?

stephen Piscura’s picture

I'm really not sure. Also, i was trying to discover who developed the site, but with no luck.

I can only share what i see in the source:

http://www.atlantaballet.com/css/responsive-tables.css
http://www.atlantaballet.com/css/jqtransform.css
http://www.atlantaballet.com/css/flexslider.css

So the responsive-table stuff comes from Foundation. I don't know, maybe that's a starting point?

Geijutsuka’s picture

Regarding the Atlanta Ballet calendar, the creator (Search Discovery) posted about it here:
http://www.searchdiscovery.com/blog/tutorial-creating-a-responsive-calendar

stephen Piscura’s picture

Cheers Geijutsuka! Thanks for sharing that link!

joserey’s picture

Thanks too.
It got me interested.

kiwad’s picture

Integrating the calendar with Calendario from Tympanus would give a great flexible solution ... I guess that would need to be made as a new module or a addon for this module... or at least it could be a good starting point for someone who wants to get a nice flexible/responsive calendar

http://tympanus.net/codrops/2012/11/27/calendario-a-flexible-calendar-pl...

brandy.brown’s picture

The last posted code is awesome! However, using the code with or without the unicode hack both produced the same gray comma. My CSS files are not compressed via config > performance FYI.

rmanola’s picture

How do I use this code in order to make the calendar responsive? I have copied it and pasted at the end of "calendar.css" but it didn't work.

stephen Piscura’s picture

Bethel Church in Redding, CA recently launched a new, Drupal-based site, including a responsive, very attractive calendar, which can be viewed here:

http://www.bethelredding.com/calendar

The theme is based on Zen. You can read a little more about it here:

https://groups.drupal.org/node/299938

The author, toddtomlinson, plans to release his solution as a contrib module.

caschbre’s picture

FYI... there is a drop-in (sandbox) module that alters the output of calendar so that it can be responsive without css hacking an html table.

https://drupal.org/node/2098587
https://drupal.org/sandbox/iconify/2087897

Calendar Plus is a companion module for Calendar. Calendar Plus runs invisibly along-side of Calendar and converts the output to responsive HTML/CSS. The module is completely self-contained so there are no files to place in your theme directory (except to style the calendar like your site theme). Additionally, Calendar Plus doesn't interfere with the normal operation of Calendar. You still manage your calendars and events using the Calendar admin tool.

The module uses an unordered list to render the month views rather than tables. When displaying on a full-sized screen, the calendar will look almost identical to the table-based display except that multi-day events won't span multiple calendar days. When viewing a month-view calendar on a tablet or smart phone, the days are displayed as a list.

hass’s picture

Can you create a patch for calendar module, please. Do not like to install extra modules.

caschbre’s picture

@hass... it's not my sandbox module. It would make sense to merge it into Calendar. Reach out to the two module maintainers and see what they say.

junedkazi’s picture

@hass I do not come across the compression issue on my site. I am running with jquery update jquery version 1.7.1. All js and css files have been aggregated.

kingfisher64’s picture

@caschbre - thanks for the post. The module does only display the start date though not end date which is a bit of an issue but there's a work around and discussion on this in the 1 open issue.

QKWS’s picture

Issue summary: View changes

Hi @hass

Where can I add the code to make my calendar responsive?

rahullamkhade’s picture

Thanks caschbre.

webservant316’s picture

#11 worked for me

hwasem’s picture

I was able to complete a variation on #11 and add in a nicely-styled date for every day of the month. This uses the Month calendar view. It may not be a strict separation of content and styling, but it works much like the calendars referenced in #13 and 20. And it is much more simple than rewriting an unordered list view. No additional modules needed.

Basically, I rewrote the cell containing each day's data to add a data-label attribute to the td element. I did this with a custom calendar-month-col.tpl.php file. I put the new tpl.php file in my theme's sites/all/theme/my-theme/templates files. Here is the contents of the file:

<?php
/**
 * @file
 * Template to display a column
 * 
 * - $item: The item to render within a td element.
 */
$id = (isset($item['id'])) ? 'id="' . $item['id'] . '" ' : '';
$date = (isset($item['date'])) ? ' data-date="' . $item['date'] . '" ' : '';
$day = (isset($item['day_of_month'])) ? ' data-day-of-month="' . $item['day_of_month'] . '" ' : '';
$headers = (isset($item['header_id'])) ? ' headers="'. $item['header_id'] .'" ' : '';

//adding the following vars to print a data-label on each day's cell. I will take that data-label and 
//print it :before the cell via css to create a header with each day's date (whether it is empty or not). I printed this new $data_label var below. 
$responsive_date = (isset($item['date'])) ?  date("l, F j, Y", strtotime($item['date'])) : '';
$data_label = (isset($responsive_date)) ? ' data-label="' . $responsive_date . '" ' : '';
?>
<td <?php print $id?>class="<?php print $item['class'] ?>" colspan="<?php print $item['colspan'] ?>" rowspan="<?php print $item['rowspan'] ?>"<?php print $date . $headers . $day; ?> <?php print $data_label ?>>
  <div class="inner">
    <?php print $item['entry'] ?>
  </div>
</td>

Then, I restyled the table to behave like a list from http://css-tricks.com/responsive-data-tables. I added css in my theme's responsive styles sheet for each breakpoint (320px, 480px, 768px). Another key point is grabbing the date from the data-label attribute (referenced in this comment http://css-tricks.com/responsive-data-tables/#comment-91835). This bit of CSS does that: td:before { content: attr(data-label); }

Here is all of my css for the calendar styling:

  /* BEGIN Calendar responsive CSS - tablet portrait */
  /* Force table to not be like tables anymore */
  .calendar-calendar table,
  .calendar-calendar tbody,
  .calendar-calendar th,
  .calendar-calendar td,
  .calendar-calendar tr  { 
	display: block; 
  }
  /* Hide table headers (but not display: none;, for accessibility) */
  .calendar-calendar thead,
  .calendar-calendar thead tr,
  .calendar-calendar tr.date-box { 
	position: absolute;
	top: -9999px;
	left: -9999px;
  }
  .calendar-calendar tr td.no-entry  { 
	border-bottom: 1px solid #ccc; 
  }
  .calendar-calendar td:before{   /* Format & Label the day headings */
	/* Now like a table header */
	width: 100%;  
	white-space: nowrap;
	clear: both;
	text-align: center;
	display: block;
	box-sizing: border-box;
	color: #ffffff;
	background-color: #a1978a;
	padding: 10px;
	content: attr(data-label); 
	height: 44px;
  }
  .calendar-calendar td.today,
  .calendar-calendar .month-view .full tr td.single-day.today{
    border-top: 2px solid #0074ab;
	-webkit-box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.25);
    box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.25);
  }
  .calendar-calendar .month-view .full td{
    padding: 0;
  }
  .calendar-calendar td,
  .calendar-calendar td.calendar-agenda-items  { 
	/* Behave  like a "row" */
	border: none;
	position: relative;
	width: 100%;
  }
  .calendar-calendar td.past{
    display: none;
  }
  .calendar-calendar td.calendar-agenda-items div.calendar{
    padding: 0;
  }
  .calendar-calendar div.calendar,
  .calendar-calendar .date-display-single,
  .calendar-calendar td span.date-display-single  {
    font-size: medium;
	font-weight: normal;
  }
  .calendar-calendar .inner .item{
    padding: 10px;
  }
  .calendar-calendar .month-view .full tr.single-day .no-entry{
    height: 44px !important;
	line-height: 24px;
  }
  .calendar-calendar .month-view .full tr.single-day .no-entry .inner,
  .calendar-calendar .no-entry .inner{
    height: auto !important;
	line-height: 1px;
  }
  .calendar-calendar .inner .views-field-title-field{
    display: inline-block;
  }
  /* END Calendar responsive CSS - tablet portrait */

I'm so thankful I found that template file! It has been a long week trying to find this solution.
Heidi

stephen Piscura’s picture

Hey there hwasem,

Many thanks for your detailed post. I'll be taking a crack at this in the next few days and i'll followup with my own experience. I so appreciate the work that you and others have put into trying to crack this nut, since it's kind of a big deal.

rwilson0429’s picture

Yes, thanks hwasem for the great details. I tried your method in #29. Without putting the css code in a media query, it changed the normal table/grid display of the calendar even when viewing from a wide screen. I didn't want that. So, I wrapped your css code in a media query:

  • @media only screen and (max-width: 760px), (min-device-width: 768px) and (max-device-width: 1024px) {

And it seem to work fine. "Grabbing the date from the data-label attribute" makes for a better user experience and makes this a better solution for me than using the css in #5.

hwasem’s picture

Good to hear it worked for you both. Yes, you will need to put the code above in media queries for each breakpoint you want to display in a list. I can't wait until our next dev cycle to release this to our mobile users. It is such an improvement on small devices.

rwilson0429’s picture

Thanks to hwasem, the above posts (#29) does a great job at making the Calendar's Month View responsive. How can the calendar's week view and Day view be made responsive as well?

hwasem’s picture

@rwilson, I'm not sure if the same approach would work. I only use the month calendar and don't have week or day experience.

There is some metadata in the day data that you may be able to use in the same fashion as the month example I gave. I'd say look around at sites with calendars that are responsive to see how you want it to look. Then try to use these tips to get it to look that way.

Sorry I can't be of more help.

rwilson0429’s picture

Thanks for the insight hwasem. I'll see what I can come up with.

kingfisher64’s picture

@hwasem - thank you very much for #29, truly superb effort.

Just to make it slightly easier for someone coming here and not having to read through quite a few posts to get a responsive calendar up and running quickly.

  1. copy #29 php code and put into a template called "calendar-month-col.tpl.php" in your sub-theme/templates directory
  2. add css on #29 to your css and wrap it with a media query/s of your choice. I used:
@media all and (max-width: 768px) {
css from #29
}

Many thanks again hwasem

hwasem’s picture

You are very welcome, kingfisher64! I'm so glad people are able to use it, too.

The code is now in production in case anyone wants to see it in action. Go to this page, http://www.midcolumbialibraries.org/calendar, and adjust your window to 768px wide or smaller. It will show our monthly calendar using the code in #29.

jcam88’s picture

FileSize
174.54 KB

I have tried #29. My header does not display, any ideas? Using Date Version: 7.x-2.9-rc1+1-dev and Calendar Version: 7.x-3.5

rothatboat’s picture

Did anyone ever successfully implement #17 - the Calendario plug-in over the Calendar module? Thanks!

hwasem’s picture

@jcam88, I'm no longer at that company, so I can't say what date version they are using for sure, but I'm pretty sure it is not dev.

I would suggest checking to make sure the template file is being picked up from your theme's sites/all/theme/my-theme/templates directory and that you cleared the cache? The data-label is not showing up in your html screen shot. The css looks good once the data-label attribute is showing up.

@rothatboat, I wasn't ever able to get that to work...hence why I finally ended up with #29.

lenoz’s picture

It's important to note that the code in #29 is for the month view only.
@hwasem does indeed mention this but it's important to be clear since the thread's title does not restrict to one view, and also the code in #29 will mess up all other views.

Tweaking #29 code to prevent messing up other views

It's not enough to change bare .calendar-calendar selectors to .calendar-calendar .month-view since this also matches the months displayed in the year view. I found the easiest way to fix this was just take a copy of the calendar-month.tpl.php template and change the opening output line from:
<div class="calendar-calendar"><div class="month-view">
to:
<div class="calendar-calendar calendar-from-<?php print $display_type; ?>"><div class="month-view">

This means we now have a calendar-from-month class we can target in our CSS that is not used by the monthly displays in the year view.

My updated version of #29 code using this new selector is below... but first, some caveats of other changes it includes:

* I do not want past dates hidden (as they were in #29).

* I would instead like empty dates (with no events on them) to be hidden.

* Fixed distrubution of padding for multiple events in any one date's block.

* Changed background colours of date headers and reduced padding a bit.

Here's the code:

/* BEGIN Calendar responsive CSS - tablet portrait */
  /* Force table to not be like tables anymore */
  .calendar-from-month table,
  .calendar-from-month tbody,
  .calendar-from-month th,
  .calendar-from-month td,
  .calendar-from-month tr  { 
	display: block; 
  }
  /* Hide table headers (but not display: none;, for accessibility) */
  .calendar-from-month thead,
  .calendar-from-month thead tr,
  .calendar-from-month tr.date-box { 
	position: absolute;
	top: -9999px;
	left: -9999px;
  }
  .calendar-from-month tr td.no-entry  { 
	border-bottom: 1px solid #ccc; 
  }
  .calendar-from-month td:before{   /* Format & Label the day headings */
	/* Now like a table header */
	width: 100%;  
	white-space: nowrap;
	clear: both;
	text-align: center;
	display: block;
	box-sizing: border-box;
	color: #ffffff;
	background-color: #888;
	padding: 5px;
	content: attr(data-label); 
	height: auto;
  }
  .calendar-from-month td.today,
  .calendar-from-month .full tr td.single-day.today{
    border-top: 2px solid #0074ab;
	-webkit-box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.25);
    box-shadow: 0px 1px 4px 1px rgba(0, 0, 0, 0.25);
  }
  .calendar-from-month .full td, .calendar-calendar .month-view .full td, .calendar-calendar .week-view .full td, .calendar-calendar .day-view td{
    padding: 0;
  }
  .calendar-from-month td,
  .calendar-from-month td.calendar-agenda-items  { 
	/* Behave  like a "row" */
	border: none;
	position: relative;
	width: 100%;
  }
  /*.calendar-calendar td.past{
    display: none;
  }*/
  .calendar-from-month td.no-entry,
  .calendar-from-month td.empty{
    display: none;
  }
  .calendar-from-month td.calendar-agenda-items div.calendar{
    padding: 0;
  }
  .calendar-from-month div.calendar,
  .calendar-from-month .date-display-single,
  .calendar-from-month td span.date-display-single  {
    font-size: 14px;
	font-weight: normal;
	margin: 0 !important;
  }
  .calendar-from-month .inner .item{
    padding: 10px 10px 0;
  }
  .calendar-from-month .inner .item:last-child{
	padding-bottom: 10px;
  }
  .calendar-from-month .full tr.single-day .no-entry{
    height: 44px !important;
	line-height: 24px;
  }
  .calendar-from-month .full tr.single-day .no-entry .inner,
  .calendar-from-month .no-entry .inner{
    height: auto !important;
	line-height: 1px;
  }
  .calendar-from-month .inner .views-field-title-field{
    display: inline-block;
  }
  /* END Calendar responsive CSS - tablet portrait */

(from a personal point of view, I haven't finished tweaking with this yet (e.g. some redundant declarations in there) but it does the job for now)

A responsive improvement for the year display

In calendar-year.tpl.php add the class year-month-view to all the month-holding tds, giving you this:

<tr><td class="year-month-view"><?php print $months[1] ?></td><td class="year-month-view"><?php print $months[2] ?></td><td class="year-month-view"><?php print $months[3] ?></td></tr>  
    <tr><td class="year-month-view"><?php print $months[4] ?></td><td class="year-month-view"><?php print $months[5] ?></td><td class="year-month-view"><?php print $months[6] ?></td></tr>  
    <tr><td class="year-month-view"><?php print $months[7] ?></td><td class="year-month-view"><?php print $months[8] ?></td><td class="year-month-view"><?php print $months[9] ?></td></tr>  
    <tr><td class="year-month-view"><?php print $months[10] ?></td><td class="year-month-view"><?php print $months[11] ?></td><td class="year-month-view"><?php print $months[12] ?></td></tr>

The following CSS is then all you should require to stack the months in the year view so that you have one month per row at your responsive screen size rather than three per row:

.year-month-view {
	display: block;
	width: 100% !important;
	box-sizing: border-box;
  }

Hope this is of some help! I may look into responsive-friendly views for day and week, and if I do I'll add these to the thread.

pslcbs’s picture

Thank you!! @hwasem (#29) @kingfisher64 (#36) and @lenoz (#41) for sharing your ideas.
It works like a charm.

But I needed to translate to spanish the month view date header using the Drual API function format_date() as explained here

I changed this:
$responsive_date = (isset($item['date'])) ? date("l, F j, Y", strtotime($item['date'])) : '';
by this:
$responsive_date = (isset($item['date'])) ? format_date(strtotime($item['date']), 'custom','l, j F Y', 'es') : '';
or this for multilanguage:
$responsive_date = (isset($item['date'])) ? format_date(strtotime($item['date']), 'custom','l, j F Y', $language) : '';

Thanks!

krug’s picture

Tnx!! @hwasem (#29) @kingfisher64 (#36) @lenoz (#41) @pslcbs (#42)
Multilanguage option works for me. Without $language
$responsive_date = (isset($item['date'])) ? format_date(strtotime($item['date']), 'custom','l, j F Y') : '';
with $language error:
Notice: Undefined variable: language in include() (line 15 of /home2/radionic/public_html/toz/sites/all/themes/jollyany/templates/calendar-month-col.tpl.php).

RichardBeacham’s picture

Implemented this just fine- thanks for advice. Stuck with multi-day events though. Has anyone ever had any luck with these?

alexberendei’s picture

Very nice work on #29 but on multi-day events it duplicate td's and mess up the order from what I've tested.

Tabestan’s picture

Has anyone successfully implemented a responsive week view?

I'm currently struggling with this, I want the table to collapse to a list on mobile.

Neslee Canil Pinto’s picture

Status: Active » Closed (outdated)