Calendars != Tables
Calendars are not semantically tables. They feel like tables because that is how we always see them, but for the data to be semantically tabular, each row would have to contain a unique entity, and they don't. In calendars the day is the entity.
The confusion lies in the fact that we also group days into weeks. People naturally think a month is a collection of weeks, but it is not, it's a collection of days. A month has, on average, 4.3 weeks. A row in a table can't contain part of an entity or multiple entities.
Row == Entity, Column == Property
Compare it to, say, a shopping cart online. The items in your cart are tabular. Each row represents one type of item in your cart. Each column is either a property of the item (name, stock number, price) or an aggregate (quantity, total amount) of a property. You never see two different item types in a single row (because it wouldn't make sense) and a cart can't contain 4.3 rows.
A Solution
For this demo I used <divs>
, one for each day set to display: inline-block
, but you'll probably want to use an <ol>
. Days flow well when changing between month/week/day views (not possible with tables). For multi-day events, Javascript can do the layout.
Demo: http://jsfiddle.net/ThinkingStiff/XXm8y/
Output:
Script:
var events = [{ from: 3, to: 9 }, { from: 4, to: 4 }, { from: 9, to: 11 },{ from: 4, to: 12 }];
for( var eventIndex = 0, event; event = events[eventIndex], eventIndex < events.length; eventIndex++ ) {
for( var dayIndex = event.from; dayIndex <= event.to; dayIndex++ ) {
var dayElement = document.getElementById( 'day' + dayIndex ),
firstDay = document.getElementsByClassName( 'event' + eventIndex ),
top;
if( firstDay.length ) {
top = firstDay[0].style.top;
} else {
var eventCount = dayElement.getElementsByClassName( 'event' ).length;
top = ( eventCount * 20 ) + 'px';
};
var html = '<div '
+ 'class="event event' + eventIndex + '" '
+ 'style="top: ' + top + ';">'
+ eventIndex
+ '</div>';
dayElement.insertAdjacentHTML( 'beforeEnd', html );
};
};
?
CSS:
#calendar {
border: 1px solid black;
height: 400px;
width: 504px;
}
.day {
display: inline-block;
height: 80px;
position: relative;
vertical-align: top;
width: 72px;
}
.day:nth-child( even ) {
background-color: pink;
}
.day:nth-child( odd ) {
background-color: lightblue;
}
.event {
background-color: lightgrey;
height: 20px;
position: absolute;
text-align: center;
width: 100%;
}
?
HTML:
<div id="calendar">
<div id="day1" class="day"></div><div id="day2" class="day"></div><div id="day3" class="day"></div><div id="day4" class="day"></div><div id="day5" class="day"></div><div id="day6" class="day"></div><div id="day7" class="day"></div><div id="day8" class="day"></div><div id="day9" class="day"></div><div id="day10" class="day"></div><div id="day11" class="day"></div><div id="day12" class="day"></div><div id="day13" class="day"></div><div id="day14" class="day"></div><div id="day15" class="day"></div><div id="day16" class="day"></div><div id="day17" class="day"></div><div id="day18" class="day"></div><div id="day19" class="day"></div><div id="day20" class="day"></div><div id="day21" class="day"></div><div id="day22" class="day"></div><div id="day23" class="day"></div><div id="day24" class="day"></div><div id="day25" class="day"></div><div id="day26" class="day"></div><div id="day27" class="day"></div><div id="day28" class="day"></div><div id="day29" class="day"></div><div id="day30" class="day"></div><div id="day31" class="day"></div>
</div>?