manix
manix

Reputation: 14747

Combine float and absolute position

I am creating a calendar where all the events are displayed in a single div. According to the top and height values, the event should be placed in a determinate place. Let me show you.

In this image, both events at 6am are at the same vertical alignment. I can solve that behavior using float: left(jsfiddle). enter image description here

If events do not have vertical alignment conflics (the height and top don't collide) then I can emulate this behavior using absolute position(jsfiddle) but NOT float. enter image description here

the issue

The real problem comes when I try to place the events at 9am and 9:40am and make them look like the image above. Asume the following properties:

That is why I tried to do something like this:

<div class="container">
    <div class="event" style="height: 50px; top: 200px; float:left;">9 AM</div>
    <div class="event" style="height: 50px; top: 230px; float:left;">9:40 AM</div>
</div>

...but float property does not work in elements with absolute position.

Overview

My idea is to treat the top value as a guide to place the event vertically in the calendar according to its hour. For example,

Ways to achieve

I tried to solve this by myself using pure ccs, but I do not mind apply javascript. However, I can not show you my attempts with javascript because I do not even can make a considerable css result. As I said before, I am using top property because I thought it could be easy position manipulation, but I could use another method if is necessary. Thank you in advance.

Upvotes: 1

Views: 987

Answers (3)

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

Using relative positioning almost solves your issue. However, it leaves gaps between events:

Fiddle #1

The only way I know to solve this problem is using absolute positioning, with JavaScript determining top and left coordinates:

var events= [].slice.call(document.querySelectorAll('.container div')),
                //array of event elements. See http://davidwalsh.name/nodelist-array
    count= [],  //running total of events during an hour. used to calculate left offset.
    i,          //loop through the events
    time,       //event time as array, such as ['6','AM']
    hour,       //event hour (1 - 24)
    minute,     //event minute (0 - 59)
    offset;     //top offset based on hour and minute

events.sort(function(a,b) {
  return a.textContent < b.textContent ? -1 : 1;
});

for(i = 0 ; i < events.length ; i++) {
  time= events[i].textContent.split(' ');
  hour= time[0].split(':')[0] * 1;
  if(time[1]==='PM' && hour !== 12) {
    hour+= 12;
  }
  minute= time[0].split(':')[1] || 0;
  offset= hour+minute/60;
  count[hour]= (count[hour] || 0)+1;
  events[i].style.top= (offset-6)*50 + 'px';
  events[i].style.left= count[hour]*100-100 + 'px';
}

Fiddle #2

Note that this code needs some tweaking to avoid events covering up other events, as you'll in the Fiddle for 12:00 PM.

Upvotes: 3

solimant
solimant

Reputation: 891

What if you use margin-top instead of top, does it work for you? You might be able to get this result:

enter image description here

You might also need to create a container div for every hour and include the underlying event divs in there:

<div class="container">
   <div class="event" style="height: 50px;">6AM</div>
   <div class="event" style=" height: 50px;">6AM</div>
</div>
<div class="container">
   <div class="event" style="height: 50px;">9 AM</div>
   <div class="event" style="height: 50px; margin-top: 25px;">9:30 AM</div>
   <div class="event" style="height: 50px; margin-top: 33px;">9:40 AM</div>
</div>

Here is some sample code on JSFiddle for reference.

Upvotes: 0

Mark
Mark

Reputation: 92440

You should add positioning to your divs. If you add position:relative to your classes you will be able to use top:xxpx to offset the vertical position. I think you will need to think about a lot of edge cases that might make a pure css solution difficult, but thought this might at least help.

Here's a fiddle: http://jsfiddle.net/markm/qvevedva/

Upvotes: 3

Related Questions