Twitterの埋め込みで手こずった際の対処法(iframe埋め込み/ウィジェットカスタマイズ/読み込み中のローディング)

# はじめに
業務でTwitterのタイムラインをページに埋め込む必要があり、いくつか問題が発生して手こずりました。
他にも同様の問題に引っかかる人がいると思うので、備忘録として解決法を残しておきます。

# 対象
- Twitterのタイムラインをiframe埋め込みしたい人
- Twitterのウィジェット埋め込みのカスタマイズ、スタイル変更したい人
- Twitterのウィジェット埋め込みをした際に発生する読み込み中の時間が長くて困っている人
- Twitterのウィジェット埋め込みをした際に発生する読み込み中のスタイルを変更したい人

# 完成品
[確認環境](https://manzoku-bukuro.github.io/twitter-widgets-loading/)
[リポジトリ](https://github.com/manzoku-bukuro/twitter-widgets-loading)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849606/6538a07b-ed6b-c956-cd9e-16b941a4bedf.gif" width="500px" />

# Twitterのタイムラインをiframe埋め込みする
私の場合、ページ内にTwitterをiframe埋め込みする必要がありました。

## 失敗)　iframeのsrc属性にTwitterのURLを指定する
まず最初に試したことは、普通にiframeのsrc属性にTwitterのURLを指定して埋め込む方法です。
試しに私のTwitterのURLを指定して埋め込んでみましょう

```html
<iframe src="https://twitter.com/manzoku_bukuro" />
```
はい、これでいっちょ上がりっと…

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849606/bbc61dfc-f9f5-4370-fed3-a2c29f8bfee5.png" width=500 />

ダメでした。Twitter側でクロスドメイン設定で拒否していますね。

## 成功) Twitter公式のウィジェットを埋め込んだページをiframe埋め込みする
まずはTwitter公式のウィジェットを活用して、ページに埋め込みます。そしてそのページをiframe埋め込みすると、無事表示することが出来ました。
まどろっこしい方法ですがこちらの方法で私は解決しました。

### Twitter公式のウィジェットでページに埋め込む
これはどこにでも乗っている情報ですね。[Twitterの公式のHelp](https://help.twitter.com/ja/using-twitter/embed-twitter-feed)に従い、Twitter公式のウィジェットを活用しました。

[こちら](https://publish.twitter.com/#)でタイムラインを表示したいユーザーのTwitterのURLを入力して、発行されたタグをページに埋め込みます。

```widgets.html
<a class="twitter-timeline" href="https://twitter.com/manzoku_bukuro?ref_src=twsrc%5Etfw">
    Tweets by manzoku_bukuro
</a>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
```

これで埋め込めました。通常ならこれで対応完了でいいのですが、私の場合案件の事情でiframe埋め込みを利用する必要があったのでさらにこちらのページをiframeで埋め込みます。

### ウィジェットを埋め込んだページをifarme埋め込みする
先ほどのウィジェットを埋め込んだページ(widgets.html)をサーバーにアップロードし、さらにそのページをiframeのsrc属性で指定します。

```html
<iframe src="~~~~~~/widgets.html" />
```
以下表示したページ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849606/235530e6-0e3c-4566-3bf2-1d0851adbe03.png" width="300px" />

ウィジェットを埋め込んだページはクロスドメイン設定で拒否していないので、**ウィジットを埋め込んだページをiframe埋め込みする**ことで表示可能となりました。

# ウィジット埋め込みのカスタマイズ
ウィジェット埋め込みした際、ウィジェットのサイズの変更をしようとして以下のようにスタイルをあてました。

```html
<a class="twitter-timeline" href="https://twitter.com/manzoku_bukuro?ref_src=twsrc%5Etfw">
    Tweets by manzoku_bukuro
</a>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<style>
.twitter-timeline {
    width: 300px;
    height: 500px;
}
</style>
```

さてどうでしょう。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849606/5c96d57e-f217-3521-9c8f-bfaad0dd5298.png" width="500px" />

まるで通用していない… 対策を考えていきましょう。

## ウィジェット埋め込み時の前提
まず前提として、発行されたタグの一部であるclassがtwitter-timelineのaタグは、読み込み完了後にaタグがTwitterのURLがsrc属性のiframeタグに置き換わる仕組みとなっています。

なのでclassがtwitter-timelineのaタグのスタイルを変更しても意味が無いわけです。

## aタグのカスタムデータ属性
aタグのスタイルを変更しても無駄といったものの、aタグにカスタムデータ属性`data-hoge="huga"`を付与することで、置き換わった後のiframeに影響を与えることが出来ます。

以下設定出来るカスタムデータ属性です。
```js
data-width="横幅" // px指定のみ ex) 300px
data-height="縦幅" // px指定のみ ex) 500px
data-lang="言語" // ex) ja/en/fr
data-theme="テーマ" // light(デフォルト) or dark
```
以上の理由から、カスタムデータ属性を指定してウィジェットのタグを作り替えます。

```js
<a class="twitter-timeline" data-lang="ja" data-width="300px" data-height="500px"  href="https://twitter.com/manzoku_bukuro?ref_src=twsrc%5Etfw">Tweets by manzoku_bukuro</a>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849606/b0498960-5c39-5084-548a-eb4b48095f8b.png" width="500px" />

**思い通り…！！**

これで指定のサイズにウィジェットを変更することが出来ました。

# ウィジェット読み込み中のローディング
ウィジェットのスタイルを調整することが出来ましたが一つだけ気に入らないことがありました。それはウィジェット読み込み中についてです。
ウィジェットの読み込みが終わるまでたまに結構な時間がかかることと、読み込み中の状態がダサいことです。以下が読み込み中の状態です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849606/ab80a095-a981-aef9-0e2c-037dc581635f.png" width="500px" />

**ダサいですね…** やれるだけやってみましょう。

出来たものがこちらになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849606/6538a07b-ed6b-c956-cd9e-16b941a4bedf.gif" width="500px" />



[完成品はこちら](https://manzoku-bukuro.github.io/twitter-widgets-loading/)
[HTMLファイル](https://github.com/manzoku-bukuro/twitter-widgets-loading/blob/main/index.html)
[CSSファイル](https://github.com/manzoku-bukuro/twitter-widgets-loading/blob/main/index.css)

以下完成形のソースです。

```index.html
<div class="twitter-area">
    <a class="twitter-timeline" data-width="300px" data-height="500px" data-lang="ja"
        href="https://twitter.com/manzoku_bukuro?ref_src=twsrc%5Etfw">
        <div class="loader"></div>
    </a>
    <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
```

```index.css
.twitter-area {
    width: 300px;
    height: 500px;
    position: relative;
    background-color: #FFF;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.twitter-area > iframe {
    z-index: 2;
}

.twitter-timeline {
    position: absolute;
    z-index: 1;
}
```

ローディングアニメーションは以下のサイトから拝借しました。

https://projects.lukehaas.me/css-loaders/

`twitter-area`というタグで全体を囲い、heightとwidthもaタグにしているものと同じものを設定し、ロード中の背景色もここで指定します。

aタグの内側にローディングアニメーションの要素を入れておけば、ウィジット読み込み完了後にaタグごと消えてくれます。

ですがウィジェット読み込み完了後、aタグが消えるまで一瞬のラグがあり、ローディングとTwitterのiframeが同時に存在する瞬間が生まれてしまいスタイルが崩れてしまいます。

なのでaタグを`position: absolute;`にしてしまえばiframeが生成された後にローディングアニメーションは後ろに隠れるのでスタイルは崩れません。

最後は少し雑でしたが、これで読み込み中のローディングアニメーションが実装出来ました。