我正在处理一个日历元素,其中一天的事件是利用网格行跨越其指定的时间框架。
然而,当涉及到设置事件宽度时,我似乎很挣扎。默认情况下,当它是当时唯一的事件时,它们将占据一天的整个宽度。如果它们在任何一点上同时发生事件,它们将相应地减少它们的宽度,以便它们都能适合。
当我有一组事件同时发生时,就会出现问题,这会生成多个列,然后在当天晚些时候发生一个事件,其中没有任何巧合的事件。此事件现在仅限于当天早些时候的事件所创建的列的宽度。
有关上下文,请参见图片:Image of annotated demo
下面是一个工作演示。
(function() {
function init() {
let calendarElement = document.getElementsByClassName('calendar')[0],
events = calendarElement.getElementsByClassName('calendar__event');
_positionEventsOnGrid(events);
}
function _positionEventsOnGrid(events) {
Array.from(events).forEach(event => {
let gridRow = event.getAttribute('data-grid-row');
if (gridRow) {
let gridRowSpan = event.getAttribute('data-grid-row-span');
event.style.gridRow = gridRowSpan ? `${gridRow} / span ${gridRowSpan}` : gridRow;
}
});
}
init();
})();
body {
margin: 0;
block-size: 100vh;
inline-size: 100vw;
}
.calendar {
$block: &;
inline-size: 100%;
block-size: 100%;
display: grid;
grid-template-columns: 2.5rem 1fr;
grid-template-rows: auto 1fr;
}
.calendar__dayNames {
grid-row: 1;
grid-column: 2;
display: flex;
}
.calendar__dayName {
flex-grow: 1;
flex-basis: 0;
}
.calendar__schedule {
grid-row: 2;
grid-column: 1/span 2;
display: grid;
grid-template-columns: 2.5rem 1fr;
border-block-start: 1px solid #000;
}
.calendar__timeline {
display: grid;
grid-template-rows: repeat(19, 1.375rem);
gap: 0 0.625rem;
grid-column: 1/ span 2;
grid-row: 1;
position: relative;
}
.calendar__timelineItem {
display: flex;
align-items: center;
border-block-end: 1px dotted #222;
}
.calendar__timelineItem:nth-child(even) {
border-block-end: 1px solid #000;
}
.calendar__timelineItem:nth-child(odd):after {
display: inline;
content: attr(data-time);
}
.calendar__dayEventsContainer {
position: relative;
grid-row: 1;
grid-column: 2;
display: flex;
}
.calendar__dayEvents {
display: grid;
grid-template-rows: repeat(19, 1.375rem);
gap: 0 0.625rem;
border-inline-start: 1px solid #000;
flex-grow: 1;
flex-basis: 0;
}
.calendar__event {
background-color: #346DA8;
border: none;
}
<div class="calendar">
<div class="calendar__dayNames">
<div class="calendar__dayName">Monday</div>
<div class="calendar__dayName">Tuesday</div>
<div class="calendar__dayName">Wednesday</div>
<div class="calendar__dayName">Thursday</div>
<div class="calendar__dayName">Friday</div>
</div>
<div class="calendar__schedule">
<div class="calendar__timeline">
<div class="calendar__timelineItem" data-time="09:00"></div>
<div class="calendar__timelineItem" data-time="09:15"></div>
<div class="calendar__timelineItem" data-time="09:30"></div>
<div class="calendar__timelineItem" data-time="09:45"></div>
<div class="calendar__timelineItem" data-time="10:00"></div>
<div class="calendar__timelineItem" data-time="10:15"></div>
<div class="calendar__timelineItem" data-time="10:30"></div>
<div class="calendar__timelineItem" data-time="10:45"></div>
<div class="calendar__timelineItem" data-time="11:00"></div>
<div class="calendar__timelineItem" data-time="11:15"></div>
<div class="calendar__timelineItem" data-time="11:30"></div>
<div class="calendar__timelineItem" data-time="11:45"></div>
<div class="calendar__timelineItem" data-time="12:00"></div>
<div class="calendar__timelineItem" data-time="12:15"></div>
<div class="calendar__timelineItem" data-time="12:30"></div>
<div class="calendar__timelineItem" data-time="12:45"></div>
<div class="calendar__timelineItem" data-time="13:00"></div>
<div class="calendar__timelineItem" data-time="13:15"></div>
<div class="calendar__timelineItem" data-time="13:30"></div>
</div>
<div class="calendar__dayEventsContainer">
<div class="calendar__dayEvents">
<button type="button" class="calendar__event" data-grid-row="1" data-grid-row-span="6"></button>
<button type="button" class="calendar__event" data-grid-row="1" data-grid-row-span="3"></button>
<button type="button" class="calendar__event" data-grid-row="1" data-grid-row-span="1"></button>
<button type="button" class="calendar__event" data-grid-row="10" data-grid-row-span="1"></button>
</div>
<div class="calendar__dayEvents">
</div>
<div class="calendar__dayEvents">
<button type="button" class="calendar__event" data-grid-row="1" data-grid-row-span="6"></button>
<button type="button" class="calendar__event" data-grid-row="1" data-grid-row-span="1"></button>
</div>
<div class="calendar__dayEvents">
</div>
<div class="calendar__dayEvents">
<button type="button" class="calendar__event" data-grid-row="1" data-grid-row-span="1"></button>
</div>
</div>
</div>
</div>
我试过几件事:网格柱:1/-1,但这将对所有事件执行此操作,因此会错误地格式化并发事件。
网格自动流:然而,在我的例子中,这似乎并不奏效。
网格-模板-柱:repeat(auto-fit,minmax()),但作为minmax的一部分的最小值需要是固定大小。
我想知道是否需要扩展positionEventsOnGrid()函数,以便它检查'grid-column:1/-1’可以应用于特定事件。如果不是和当时的其他事件巧合的话。然而,我觉得这可能是相当复杂的,所以我想我会问周围的情况下,有一个更简单的方法。
我希望单一事件跨越他们一天的整个宽度,而不管当天早些时候或晚些时候是否有并发事件。
1条答案
按热度按时间slsn1g291#
解决方案中的网格列是隐式生成的,因为CSS没有显式设置列布局。参见@Michael Benjamin的回答here。
问题是数字索引(1 / -1)只适用于显式网格。换句话说,就是具有已定义的列和行的网格。您使用的是隐式网格,其中的列和行根据需要自动生成。
如果您将
grid-template-columns: repeat()
设置为.calendar__dayEvents
容器的CSS规则,则应用于.calendar__event
元素的event.style.gridColumn = 1 / -1;
将扩展到所有列。这与您的评论“作为minmax的一部分的最小值需要是固定大小”类似重叠和非重叠事件
我想知道是否需要扩展positionEventsOnGrid()函数,以便它检查'grid-column:1/-1’可以应用于特定事件。如果不是和当时的其他事件巧合的话。然而,我觉得这可能是相当复杂的,所以我想我会问周围的情况下,有一个更简单的方法。
我还没找到解决的办法。幸运的是,在SO上存在可以group overlapping time or integer intervals的现有解决方案。在我的日历组件中,我已经应用/改编了我在链接的SO帖子上发布的GitHub功能。调整应用于下面的代码片段。
下面的代码段执行以下操作:
data-type
属性的事件的背景色。JS执行
event.style.gridRow
进行布局。window
函数getComputedStyle()
检索的,如本文所提供的:count columns in a responsive grid。.calendar__dayEvents
网格容器,并将非重叠事件项设置为event.style.gridColumn = 1 / -1;
。event.style.gridColumn = 1 / span ${gridColumnCount};
设置列数值,而不是为grid-template-columns
事件网格容器设置网格列数。(请参见代码段中的注解。)更新(9/26/2023)
添加了带注解的图像作为替代代码执行描述。
.calendar__dayEvents
div容器(即,用黄色标出的每一天的列)。.calendar__event
元素分组为具有重叠间隔的元素(用红框标出)。.calendar__dayEvents
div container/day-of-week列中布局所有.calendar__event
元素。.calendar__event
元素,只有1个.calendar__event
条目.calendar__dayEvents
div容器,并在重叠组中设置.calendar__event
元素,只有1个.calendar__event
条目来跨越所有列(通过style.gridColumn = 1 / -1
)。