2

I'm working on an application that contains a custom calendar. The calendar is styled with Flexbox (all the building / date logic is handled with React).

The calendar is functioning great, but I'm having a styling problem I'm not sure how to solve.

When lots of events are added in a particular week, I'd like the week div to overflow: auto; (show a scrollbar) so that you can view all of the events.

The problem I am having is a height issue on the day divs. I don't have a fixed height on the parent (week div) since I am using flexbox with flex: 1; to fill the space. How can I get the children (day divs) to use the entire height of the overflowing parent (week div)?

I'd prefer to have a CSS only solution that works cross-browser.

Sample CodePen Here: https://codepen.io/anon/pen/jLQyxX?editors=0100

HTML:

<div class="calendar">
  <div class="week">
    <div class="day">6</div>
    <div class="day">7</div>
    <div class="day">8</div>
    <div class="day">
      <div>This</div>
      <div>Border</div>
      <div>Doesn't</div>
      <div>Scale</div>
      <div>Correctly</div>
      <div>(Scroll Down)</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
    </div>
    <div class="day">10</div> 
  </div>
</div>

CSS:

body {
  display: flex;
  flex: 1;
  padding: 0;
  margin: 0;
  height: 100vh;
}

.calendar {
  display: flex;
  flex: 1;
  flex-direction: column;
  border: 1px solid black;
  border-bottom: none;
  margin: 15px;
}

.week {
  display: flex;
  flex: 1;
  overflow: auto;
  border-bottom: 1px solid black;
}

.day {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: 10px;
  outline: 1px dotted red;
}
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Justin
  • 524
  • 5
  • 19
  • 1
    At all possible to put a scrollbar in the `day` element? – Adam Jenkins Aug 29 '17 at 17:38
  • Alternative is to fake the borders of the day elements by using a CSS background gradient and remove the outlines from them altogether. That's the only thing stopping your `day` elements from looking like they are full height. – Adam Jenkins Aug 29 '17 at 17:43
  • @Adam I did experiment with that at first when running into my posted issue. Unfortunately, it doesn't work for my case as the events can run across several days (similar to FullCalendar https://fullcalendar.io/) – Justin Aug 29 '17 at 17:43
  • 1
    @Michael_B Thanks for sharing the link - I was expecting that there would be no easy CSS solution - aside from some creative "hacking" to get the desired look. I did quite a lot of searching on the web for this issue and that link never came up. – Justin Aug 29 '17 at 17:52

2 Answers2

2

One possible solution would be to add a wrapper wrap between the week and day
This works on Chrome/Firefox/Edge, IE though, has some issue I am looking into, and don't have Safari to test it on.

Updated codepen

Stack snippet

body {
  padding: 0;
  margin: 0;
  display: flex;
}

.calendar {
  flex: 1;
  border: 1px solid black;
  box-sizing: border-box;
  border-bottom: none;
  margin: 15px;
  height: calc(100vh - 30px);
  display: flex;
  flex-direction: column;
}

.week {
  flex: 1;
  min-height: 20%;
  overflow: auto;
  border-bottom: 1px solid black;
  box-sizing: border-box;
}

.week .wrap {
  display: flex;
  min-height: 100%;
}

.day {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: 10px;
  outline: 1px dotted red;
}

.week:nth-child(even) .day {
  background: lightgray
}
<div class="calendar">
  <div class="week">
    <div class="wrap">
    <div class="day">1</div>
    <div class="day">2</div>
    <div class="day">3</div>
    <div class="day">4</div>
    <div class="day">5</div> 
      </div>
  </div>
  <div class="week">
    <div class="wrap">
    <div class="day">6</div>
    <div class="day">7</div>
    <div class="day">8</div>
    <div class="day">
      <div>9</div>
      <div>&nbsp;</div>
      <div>This</div>
      <div>Border</div>
      <div>Doesn't</div>
      <div>Scale</div>
      <div>Correctly</div>
      <div>(Scroll Down)</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
      <div>...</div>
    </div>
    <div class="day">10</div> 
    </div>
  </div>
  <div class="week">
    <div class="wrap">
    <div class="day">11</div>
    <div class="day">12</div>
    <div class="day">13</div>
    <div class="day">14</div>
    <div class="day">15</div> 
  </div>
  </div>
  <div class="week">
    <div class="wrap">
    <div class="day">16</div>
    <div class="day">17</div>
    <div class="day">18</div>
    <div class="day">19</div>
    <div class="day">20</div> 
  </div>
  </div>
  <div class="week">
    <div class="wrap">
    <div class="day">21</div>
    <div class="day">22</div>
    <div class="day">23</div>
    <div class="day">24</div>
    <div class="day">25</div> 
  </div>
  </div>
</div>

Since your main grid keeps an equal size per day (use flex: 1 to fill remaining space), another option would be to use absolute positioning for the week and day, and then make day a flex container to handle its content.

Asons
  • 84,923
  • 12
  • 110
  • 165
  • This works quite well for my use case - thank you. I did test Safari and saw that it didn't work well but it was on an old version and I don't have a more updated Mac to test on easily. Fortunately, this is for an internal application and we don't have any Safari users. – Justin Aug 30 '17 at 14:43
-1

The best way to do it is moving the overflow: auto from .week to .day