「プリザンターのダッシュボード」×「Metabaseの埋込」でレスポンシブ対応をさせる方法

## はじめに
プリザンターのダッシュボード機能のカスタムHTMLパーツを使用してMetabaseの埋込あいてむをレスポンジブ対応＆パーツサイズの可変サイズに動的に対応させる方法を紹介します。

## 現状を見てみる
Metabaseで埋込用の要素を取得すると次のようになっています。

``` html
<iframe
    src="https://*****/public/question/e05274f1-3388-4211-8586-8a0ce21be55b"
    frameborder="0"
    width="800"
    height="600"
    allowtransparency
></iframe>
```
これをカスタムHTMLパーツでそのまま埋込するとこのような表示になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555395/f1ad7c99-e3fc-489c-940f-ca88627ecab8.png)
パーツのサイズに関係なく、要素中で指定されているサイズそのままで表示されます。サイズも固定値のため要素のサイズやウインドウのサイズを変えても何も変わりません。

## サイズ指定を外してみる
先ほどのHTMLからサイズ指定を外してみます。
``` html
<iframe
    src="https://*****/public/question/e05274f1-3388-4211-8586-8a0ce21be55b"
    frameborder="0"
    allowtransparency
></iframe>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555395/69f69851-f7f5-4f93-8aa4-cdb0556becce.png)
最小サイズ表示になります。

## サイズ指定を入れてみる
要素にフィットさせるとなると、iframe自体に要素サイズを指定することを思いつきます。まずは、要素に直接サイズを指定してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555395/99580999-6392-4658-8eaf-002fb872d390.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555395/42c1a32e-fc91-41e8-a427-883db82a237c.png)
横幅は想定通りに要素いっぱいまで広がりましたが、高さが広がりません。

## 実際の要素を見てみる
実際の要素を見てみると`.grid-stack-item  > #DashboardPart_1 > .dashboard-custom-html-body`とカスタムHTMLは3つの要素にくるまれていることが分かります。
```html
<div class="grid-stack-item ui-resizable-autohide" gs-x="0" gs-y="0" gs-w="12" gs-h="52" gs-id="1">
    <div class="grid-stack-item-content">
        <div data-id="1" id="DashboardPart_1">
            <div class="dashboard-custom-html-body">
                <iframe src="https://*****/public/question/e05274f1-3388-4211-8586-8a0ce21be55b" frameborder="0" allowtransparency="" style="
    width: 100%;
    height: 100%;
"></iframe>
            </div>
        </div>
    </div>
    <div class="ui-resizable-handle ui-resizable-se" style="z-index: 100; user-select: none;"></div>
    <button id="DashboardRefresh_1" type="button" class="dashboard-part-refresh" style="opacity: 0;">
        <span class="material-symbols-outlined">refresh</span>
    </button>
</div>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555395/f435cc09-cf57-45ec-8a4b-eabb95052b10.png)
ここで重要になるのは`.grid-stack-item-content`です。この要素にセットされているCSSは次のようになっています。
```css
.grid-stack>.grid-stack-item>.grid-stack-item-content {
    margin: 0;
    position: absolute;
    width: auto;
    overflow-x: hidden;
    overflow-y: auto;
}
```
`position`要素に`absolute`が指定されています。ということはここで、高さを見失っていることが分かります。

## スタイルを作ってみる
高さ方向の指定をしてあげればOKということが分かったので、それを補うCSSを作成します。全てのiframeに適用されてしまうと、Metabase以外のifraceにも適用されてしまい面倒なので、Metabaseで生成された埋込コードを下記の様に編集して使用します。
```diff_html
<iframe
    src="https://*****/public/question/e05274f1-3388-4211-8586-8a0ce21be55b"
    frameborder="0"
-    width="800"
-    height="600"
+    class="metabase_iframe"
    allowtransparency
></iframe>
```
先ほどの埋込コードへの編集をふまえたCSSは次の通りです。
```css:DashboardIframeFit.css
:has(.metabase_iframe) {
    .grid-stack > .grid-stack-item > .grid-stack-item-content {
        height: calc(100% - 20px);

        div[id^=DashboardPart] {
            height: 100%;

            .dashboard-custom-html-body {
                height: 100%;

                iframe {
                    height: 100%;
                    width: 100%;
                }
            }
        }
    }
}
```
これをサイトの管理のスタイルに追加して動きを見てみます。
![レコーディング-2025-03-10-145710.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555395/c047ad83-21bd-4d9a-8480-9003041acd33.gif)
Metabaseのiframe上のイベントと一部競合するためポインタの動きに引っかかりが出てはいますが、レスポンシブについては正常に動作することが確認出来ました。全てのダッシュボードにこの動きを適用するなら、拡張スタイルに設定してしまえばOKです。

## まとめ
ダッシュボードにMetabaseの埋込コードを埋め込んだときにレスポンシブ対応をさせる方法を紹介しました。この方法、他のiframeにも使える技なので是非使ってみてください。