Fullcalendarで画面サイズが小さい時に重なったイベントの幅が狭くなりすぎるのを解決

技術備忘録

Fullcalendarでスマホのような画面サイズが小さいディスプレイ利用時で、同じ時間帯に3つ以上のイベントがあると下記のように不自然にイベント幅が狭くなってしまいます。これをeventDidMount上でCSSを書き換えることによって解決します。

2021年1月30日追記

iOS safari上だと重ねて表示されませんでした。原因はinsetが効かないためっぽいです。修正方法をページ下部に記しておきます。

スポンサーリンク

slotEventOverlap

まずこの問題で検索すると、slotEventOverlapが出てきます。このパラメータはデフォルトでtrueとなっていて、複数のイベントが重なる時いい感じにスタイリングされると書いてあります(events will overlap each other)。しかしながら、スマホの画面サイズでは上記の図のようにイベント間に隙間ができて不自然に狭くなります。これをfalseに変更すると以下のようになります。

しかしこれでは9:00~11:00のイベントは不必要に幅が狭くなってしまっていて、見にくくなってしまっています。ここをもう少し改善したいと思います。

スポンサーリンク

eventDidMountでCSSを修正

developer toolでstyleを分析すると、class=”fc-timegrid-event-harness fc-timegrid-event-harness-inset”で下記のような記載があり、inset内の二つ目の66.6667%を0%にすると横幅いっぱいに表示されるようになりました。そこでこの数値をイベントごとに修正できるようにしたいと思います。

element.style {
    z-index: 1;
    inset: 404px 66.6667% -494px 0%;
}

修正はeventDidMount内で行います。

import $ from 'jquery'

const eventDidMount = (args) => {
    let parent = $(args.el).parent()
    if (parent.css('z-index')!=='auto'){ // allDayイベントでなければz-indexはautoとなる
        let insets = parent.attr('style').split('inset: ').slice(-1)[0].replace(';', '').split(' ')
        insets[1] = '0%'
        parent.css({'inset': insets.join(' ')})
    }
}

return (
    <FullCalendar
        ...
        eventDidMount={eventDidMount}
        slotEventOverlap={false}
        ...
    />
)

注意点として、parent.css(‘inset’) によってinsetの内容を取得すると、なぜか一部のイベントで以下のように最後の~%の値が省略されているものが生じました。それを防ぐためにparent.attr(‘style’)でスタイルの値を取得しています。

> parent.css('inset')

// 取得したい値の形式
'404px 66.6667% -494px 0%'

// 一部のイベントで取得される値の形式
'404px 66.6667% -494px'
スポンサーリンク

追記:iOS safariでの表示に対応

iOS safariだと?insetで指定した値に配置してくれないっぽく、下記のように直接top, right, bottom, leftの値を指定しました。

const eventDidMount = (args) => {
    let parent = $(args.el).parent()
    if (parent.css('z-index')!=='auto'){ // allDayイベントでなければz-indexはautoとなる
        let insets = parent.attr('style').split('inset: ').slice(-1)[0].replace(';', '').split(' ')
        insets[1] = '0%'
        // parent.css({'inset': insets.join(' ')})
        parent.css({top: insets[0], right: insets[1], bottom: insets[2], left: insets[3]})
    }
}

これで複数のイベントが重ねて表示できたのですが、なぜかイベントに収まりきらない文字がはみ出て表示されてしまいました。そこでcssを編集します。

.fc-event-title-container{
  overflow:hidden;
}

コメント

タイトルとURLをコピーしました