About Blog Contact

WordPressのセキュリティをより効果的にするためのプラグイン『SiteGuard』設定方法と非常時の対処法

サイトを作るとなるとWixやStudioなどノーコードツールを使われることが多くなりましたが、Wordpressの利用率はまだまだトップを走り続けています。

特に、自分でブログサイトを立ち上げるとなったときにはWordpressを選ぶ方は多いと思います。

でも、その一方でこんな不安、ありませんか?

「もし、せっかく書いた記事や作ったブログが、悪意のある誰かに乗っ取られたり、壊されたりしたらどうしよう…」

考えただけで、ゾッとしますよね。

でもセキュリティをしっかり設定することで、多くの脅威から自分のサイトを守ることができます。

「でも、セキュリティってなんだか難しそう…」「専門用語ばかりで、設定を間違えたら逆にブログが見られなくなりそうで怖い…」

そんな不安があっても大丈夫!

手っ取り早く、簡単で堅牢なセキュリティ対策ができる、”無料”の門番『SiteGuard WP Plugin』プラグインをご紹介します。

そもそもSiteGuardって、どんな”門番”?

SiteGuardは、例えるなら「優秀で頼りになる家の警備員」みたいなものです。

具体的には、空き巣(不正アクセス)が嫌がることを、全部先回りしてやってくれます。

  • 家の場所を分かりにくくする(管理画面のURLを変更)
  • 玄関の鍵を特殊なものに変える(ログインページのURLを変更)
  • 「この人は本当に家の住人?」と本人確認する(画像認証)
  • 何度も鍵をガチャガチャする不審者を締め出す(ログインロック)

これだけでも対応範囲が広いですよね。

より詳しい情報を知りたい方は公式サイトをご覧ください。

[

SiteGuard WP Plugin

SiteGuard WP Plugin は、管理ページとログインへの攻撃からの保護に特化したプラグインです。

ja.wordpress.org

](https://ja.wordpress.org/plugins/siteguard/ "SiteGuard WP Plugin")

SiteGuardのメリットと、たった1つの注意点

【メリット】

  • 無料なのに高機能:これ一つで基本的なセキュリティ対策はバッチリです。
  • 安心の日本製:管理画面もすべて日本語なので、直感的に使えます。
  • 設定が比較的かんたん:この記事を読めば、15分ほどで完了します!

【たった1つの注意点(デメリット)】

  • 設定を間違えたり、設定した内容を忘れると、自分もログインできなくなる可能性がある

「えっ、やっぱり怖いじゃん!」と思うかもしれませんが大丈夫です!

この記事では、そうならないための**「絶対にやっておくべき2つの準備」**からお教えします。これさえやっておけば、何も怖くありません。安心してついてきてくださいね!


設定前にこれだけはやって!2つの”お守り”

万が一の事態に備えて、作業を始める前に、2つの「お守り」を準備しましょう。たったこれだけで、安心感がまったく違いますよ。

お守り①:ログインURLをコピーして、メモ帳に貼っておく

これから、ログインページのURL(住所)を変更します。もし新しい住所を忘れてしまうと、自分のお家に帰れなくなってしまいますよね。

今のうちに、現在のログインURL( https://あなたのドメイン/wp-admin/ など)をコピーして、PCのメモ帳や手帳に貼り付けておきましょう。

お守り②:バックアップを取っておく

「バックアップ」とは、今のブログの状態をまるごと保存しておくことです。もし何かあっても、このバックアップがあればすぐに元通りに復元できます。

バックアップができたら、それではいよいよ「SiteGuard」を設定していきましょう!


SiteGuardかんたん設定

ここからは、実際の画面を見ながら一つずつ進めていきましょう。

  1. WordPressのダッシュボード(管理画面)左側メニューから「プラグイン」→「新規追加」をクリック。
  2. 右上の検索窓に「SiteGuard WP Plugin」と入力。
  3. 「今すぐインストール」をクリックし、その後「有効化」をクリックします。

これだけで、あなたのブログに警備員が常駐してくれるようになりました。

でも、ただいるだけではダメですよね。警備員に「ここを重点的にお願いします」と指示を出していきましょう。

左側メニューに「SiteGuard」という項目が追加されているので、クリックしてください。

① 管理ページアクセス制限

これは、ログインしていないIPアドレスから管理画面(wp-admin)にアクセスできなくする設定です。

一度管理ページにアクセスしてログインすると、その時のIPアドレスが記録され、それ以外のIPアドレスではログイン状態を保たない

  • 設定方法: 「管理ページアクセス制限」タブを開き、「ON」にするだけでOKです。

② ログインページ変更

これが一番大事な設定です。

WordPressのログインページは、初期設定だとURLがバレバレ( ドメイン名/wp-login.php )なので、空き巣に狙われやすいんです。

そこで、ログインページのURLを、あなたしか知らないオリジナルの名前に変更してしまいましょう。

  1. 「ログインページ変更」タブを開きます。
  2. 「ログインページURLを変更する」を「ON」にします。
  3. 「変更後のログインページ名」に、あなただけの好きな半角英数字を入力します。(例: login_12345 など)
  4. 一番下の「変更を保存」をクリックします。

超重要ポイント!新しいログインURLを忘れないようにしよう

保存ボタンを押した瞬間に、あなたのブログのログインページのURLが変わります!
新しいログインページのURL( https://あなたのドメイン/login_12345 )は、絶対に忘れないでください!

  • 今すぐブックマーク(お気に入り登録)しましょう!
  • スマホで写真に撮っておきましょう!
  • 手帳にメモしておきましょう!

ログインできなくなった

もし、万が一、本当に万が一忘れてしまったら…落ち着いてください。

サーバーの「ファイルマネージャー」という機能(サーバーのサービスによって名称は変わります)やFTPソフトを使って、SiteGuardの設定を一時的にオフにすれば元に戻せます。

SiteGuardを一時的に無効にする方法

ファイルマネージャーやFTPの設定などは長くなるのでここでは割愛します。

ここでは簡単な流れをご説明します。

  1. FTPやファイルマネージャーにログインする。
  2. WordPressをインストールしているフォルダに移動し、「wp-content」→「plugins」フォルダに移動する。
  3. 「siteguard」フォルダの名前を変更する(例.siteguard_offや_siteguardなど)
  4. 前のログインページ( https://あなたのドメイン/wp-admin/ など)にアクセスしてログインする。
  5. ログインできたら③で変更したフォルダ名を元に戻す。
  6. SiteGuardの設定が戻っているか確認し、ログインURLを確認してブックマークなどする。

ざっとこんな感じです。

新しいログインURLは厳重に管理しましょう。

③ 画像認証

これは、ログイン画面に「ひらがなの画像認証」を追加する機能です。機械(ボット)による自動的な不正ログイン攻撃を防ぐのに、とても効果的です。

  • 設定方法: 「画像認証」タブを開き、「ひらがな」にチェックが入っていることを確認して「ON」にするだけ!

次回ログイン時には、IDとパスワードの他に「ひらがな」入力欄が追加されていますので、よりセキュリティは強力になります。

④ ログイン詳細エラーメッセージの無効化

これは、通常だとログインに失敗したときに、「ここが間違ってますよ~」と失敗の原因箇所を教えてくれるところを、失敗した箇所がユーザー名であろうがパスワードであろうが同じエラーメッセージを表示するようにしてくれます。

これによって、入力したユーザー名が存在するかどうかを不正アクセス者に知られにくくすることができます。

mimihokuro

mimihokuro

どこが間違ってるか教えてくれると管理者には嬉しいんですが、不正アクセス者にとってもありがたいことなので、この機能は有効にしておくのがオススメです。

⑤ ログインロック

これは、ログインに何度も失敗した相手(IPアドレス)からのアクセスを、一定時間ブロックしてくれる機能です。

この機能はブルートフォースアタック(総当たり攻撃)によるログインへの試みを防ぐ効果があり、必須で有効にするべきといっていい項目です。

⑥ ログインアラート

こちらはその名の通り、ログインしたらメールで通知してくれる機能です。

設定画面を開くと、通知するメールの内容を編集することができますが、基本的に変更なしで問題ありません。

⑦ フェールワンス

この機能は、正しいログイン情報を入力しても1回失敗させることで、「リスト攻撃」というサイバー攻撃を防ぎやすくするための機能です。

リスト攻撃とは、パスワードのリストを使って、たくさんのアカウントにログインを試みるサイバー攻撃のことで、1回失敗させれば「そのパスワードは合っていない」と認識させることができるので、悪意ある攻撃を防ぎやすくなります。

⑧ XMLRPC防御

XML-RPC ピンバックを利用したDDoS攻撃と、XML-RPC を利用したブルートフォースアタック(総当たり攻撃)を防ぐ機能です。

本来、ピンバックは他のブログ記事で自分のブログ記事が引用された際に、引用元に通知を送るための仕組みです。

これにより、ブログ間の連携がスムーズになるのですが、これを悪用することで大量の無効または偽装されたピンバックリクエストが同時に押し寄せることで、サーバーは正規のアクセスを処理できなくなり、結果としてWebサイトやサービスが停止してしまう恐れがあるのです。

基本的にWordpress初心者の方は、この機能を有効にしておきましょう。

mimihokuro

mimihokuro

私も履歴を見たら過去にブルートフォースアタックをされたことが分かり、個人ブログでもこんなにアタックされるのかとゾッとした経験があります・・・🥺

⑨ ユーザー名漏えい防御

WordPressの仕組み上、何も対策をしていないとユーザー名を特定することができてしまいます。

例えば、https://yourwebsite.com/?author=1といったURLにアクセスすると、投稿者IDが 1 のユーザーのプロフィールページや投稿一覧が表示されるようになっています。

たとえ、表示名が直接ユーザー名と一致しなくても、その投稿者IDを持つユーザーが何らかの投稿をしていれば、その投稿者IDは「存在する」ことが確認できてしまうので、これは設定必須の項目といっても過言ではありません。

⑩ 更新通知

こちらもその名の通り、更新できるプラグインやテーマなどがあったときにメールで通知してくれる機能です。

常に最新の状態に保つことがセキュリティを維持する基本中の基本ですね。

必要な設定は以上です。お疲れ様でした!
実は、基本的な設定はこれだけで完了です!思ったより簡単じゃありませんでしたか?

最後に、設定内容をすべてチェックしたら、一度ログアウトして、新しいログインページのURLから、きちんとログインできるか試してみましょう。

まとめ:最強の門番を手に入れて、安心してブログを育てよう!

本当にお疲れ様でした!
これで、あなたのブログのセキュリティは格段にアップしました。もう、夜も安心して眠れますね(笑)。

でも、SiteGuardの設定ができたからといってセキュリティ対策を放置するのはNGです。

定期的に不正アクセスをされていないか、されそうになったか、その痕跡をチェックすることなども大事です。

セキュリティ対策は、いわば「ブログ運営の土台作り」です。この面倒な作業を乗り越えたあなたは、もう立派なブロガーの一歩を踏み出しています。

あなたのブログが、たくさんの人に愛される素敵な場所に育っていくのを、心から応援しています!

WordPressで階層を変更したならRedirectionプラグインでサクッとリダイレクト設定

サイトのドメインを変えたり、ページの階層を変えたときにほぼ必須の作業なのがリダイレクト設定。

でもGoogle検索にすでにインデックスされている場合は、前のURLについていたGoogleからの評価を新しいURLに引き継がせるために、301リダイレクトを設定する必要があります。

そこでやることとして、.htaccessやサーバーサイドスクリプトなど設定には方法がありますが、これが難しい、というか触るのが怖いということで、非エンジニアには高いハードルになるわけです。

WordPressを使っているとWordPress自体やテーマによって.htaccessに自動で書き込まれたりするので、非エンジニアには余計に難解に・・・。

そこで手軽なのがプラグイン「Redirection」です。やっぱり便利なプラグインです。

Redirectionのリダイレクト設定

記事ページの階層を変更した場合を例にしたRedirectionのリダイレクト設定です。

RedirectionはWordpress内で検索して出てくるので、インストールしておきましょう。※ここではインストール手順は割愛します。

WordPressの設定→ホームページ設定を「最新記事」にしていて、「ドメイン名/投稿記事ページ」になっていたものを、トップページと投稿ページに特定の固定ページに設定して、「ドメイン名/blog/投稿記事ページ」といった具合に、パーマリンクに/blog/を追加したとします。

つまり、

旧URL:https://example.com/post-slug/

から

新URL:https://example.com/blog/post-slug/

変更した場合ですね。

設定方法を順を追って見ていこう

まず基本的な設定として、指定のURLにアクセスしたときに「ドメイン名/blog」にリダイレクトするための設定の流れを見ていきましょう。

基本的な設定の流れ

  • STEP1

    Redirectionをインストールして有効化すると「ツール」直下に「Redirection」という項目が追加されているのでクリックする

  • STEP2

    Redirectionの設定画面が開いたら「新しいリダイレクトを追加」する

    ■ソースURL(リダイレクト元)

    ^/([^/]+)/$

    ■ターゲットURL(リダイレクト先)

    /blog/$1/
  • STEP3

    「正規表現を使用」にチェックを入れる

  • STEP4

    HTTPコードを301(恒久的)に設定

  • STEP5

    「追加」ボタンを押して登録する

リダイレクト先の設定に使用している$は正規表現の一種で、リダイレクト元の設定内で()で囲まれた部分を1つの「グループ」と考えて、$1の場合は1つ目のグループを、$2の場合は2つ目のグループをリダイレクト先のURLに置き換えることになります。

特定のページをリダイレクトさせないように設定する方法

さて、ここで一つ問題があります。

先ほどの例(/blog/に階層変更)だと階層の変更は投稿関連のページのみで、プロフィールページや問い合わせページといった固定ページ(例:aboutやcontact)は何も変わっていないのでリダイレクトする必要ないのに、ポーンとリダイレクトされてしまいます。

なので、固定ページのような階層の変更がないページの除外設定が必要です。

除外設定方法

除外設定としては、こちらも正規表現で除外することを明記します。

先ほどの設定ではドメイン配下のページすべてが対象でした。

^/([^/]+)/$

プロフィール(about)、問い合わせ(contact)、プライバシーポリシー(privacy-policy)の3つを除外する場合は、上記の記法からこんな感じに書き換えます。

^/(?!about|contact|privacy-policy)([^/]+)/$

mimihokuro

mimihokuro

リダイレクト先の設定は/blog/$1/のままでOKです

これで指定の固定ページではリダイレクトが除外されるようになります。

一括リダイレクト設定の設定漏れでログインできなくなることも

特定のページをリダイレクトさせないように除外設定する際、固定ページだけに意識が行きがちですが、意外に忘れがちなのがWordPressがインストールされているディレクトリ配下へアクセスしたときの除外設定です。

ドメイン配下のページすべてをリダイレクト設定しているので、固定ページだけでなく、ログインページもリダイレクトの対象になるので、こちらも忘れずに除外設定しておきましょう。

さもないと、一度ログアウトしてしまうと次回以降ログインしようと思ってもリダイレクトされてログインできなくなってしまいます😱

mimihokuro

mimihokuro

私もやらかしてログインしたいのにリダイレクトされてログインできなくなってしまいました・・・💦

ログインできなくなったときにはどうすればいい?

もし除外設定を忘れてログインできなくなってしまった場合は、FileZillaのようなFTPソフトやXサーバーのサーバーパネルのような管理画面などからディレクトリ操作する必要があります。

ログインできない問題の解決までの流れ

  • STEP1

    FTPソフトやファイル管理画面からWordpressがインストールされているディレクトリにアクセスする

  • STEP2

    /wp-content/plugins/へディレクトリ移動する

  • STEP3

    redirectionディレクトリを探してディレクトリ名を適当な名前に変更する

    プラグインのディレクトリ名を変更すると、変更したプラグインがWordpressの管理画面から読み込めなくなるので、一時的にRedirectionが無効化されます。

  • STEP4

    今まで通りにログイン画面からログインする

  • STEP5

    STEP3で変更したredirectionディレクトリを元の名前に戻す

  • STEP6

    Redirectionの設定画面でログインページなどを除外設定する

mimihokuro

mimihokuro

「リダイレクト設定忘れてログインできない!どうしよう!💦」と焦らず、落ち着いて上記の方法を試してみてください。

RedirectionはWordpressを扱う方には簡単で便利なプラグインなので、.htaccessを使って301リダイレクト設定するのが怖い、難しいと感じる方はぜひ試してみてください!

CSSによる「部分一致」でスタイルを一括適用させる方法&効かないときのポイント

CSSで複数のクラスやIDに同じスタイルを適用させるとき、どうしてますか?

.class-name1, .class-name2, #id1 { // 適用したいスタイル }

こんな感じが多いと思います。
でも適用したいクラスやIDを羅列するのはコードが見にくくなるし、何よりめんどくさい・・・ですよね?
そんなときに便利なのが部分一致!
今回は一括でスタイルを適用させられて、かつコードがスッキリする便利な「CSSによる部分一致」のお話です。

部分一致の基本

前方一致

前方一致は、要素のクラス名やIDの先頭が指定の文字列で始まっている場合に使えて、^=という書き方をします。

[id^="section-"] { // 適用したいスタイル }

例えば、[id^="section-"]とすることで、ID名がsection-で始まる全ての要素にスタイルを適用させることができます。

後方一致

後方一致は、要素のクラス名やIDの末尾が指定の文字列で終わっている場合に使えて、$=という書き方をします。

[class$="-item"] { // 適用したいスタイル }

例えば、[class$="-item"]とすることで、クラス名が-itemで終わる全ての要素にスタイルを適用させることができます。

部分一致

部分一致は、要素のクラス名やIDに指定の文字列含まれている場合に使えて、*=という書き方をします。

a[href*="/file/"] { // 適用したいスタイル }

a[href*="/file/"]とすることで、aタグのhref属性で/file/を含む要素にスタイルを適用させることができます。

この属性セレクタが一番柔軟にスタイルを適用させやすい反面、柔軟すぎるがゆえにスタイルを適用させたくない要素にも反映されてしまうリスクが高くなるデメリットがあります。
例えば、[class*="item"]としたとき、

  • class="item"
  • class="item-list"
  • class="main-item"

といった、意味合いが違う要素にも同じスタイルが反映されてしまいますので注意が必要です。

部分一致(単語一致)

こちらも部分一致ですが、先ほどの部分一致よりも厳格なチェックが行われ、要素のクラス名やIDに指定の“単語”が含まれている場合に使えて、~=という書き方をします。

[class~="logo"] { // 適用したいスタイル }

「*=」と「~=」の違いは?

*=と違いがよく分からないと思いますので、下の例をご覧ください。

<!-- 「~=」が適用される例 -->
<a class="logo">Logo</a>
<a class="header logo footer">Logo</a>

<!-- 「~=」が適用されない例 -->
<a class="logotype">Logotype</a>
<a class="logomark">Logo</a>

適用されるものとされないもので何が違うかをこの例でいうと、logoという単独の単語であるかどうか、ということです。
つまり、logotypeだとlogotypeという単語として認識されてしまい、logoという単語とは一致しないということになってしまいます。

言ってしまえば、*=は指定の文字列を含む部分一致、~=はほぼ完全一致になります。

部分一致セレクタ早見表

つらつらと書いてしまいましたので、パッと見で知りたい方は早見表をどうぞ!

セレクタ記述例対象のa文字列適用されるタグ
^=section[id^="section-"]section-section
$=li[class$="-item"]-itemli
*=a[href*="/file/"]/file/a
~=img[class~="logo"]logoimg

便利だけどこんな落とし穴も

部分一致は柔軟で使い勝手のいい方法ですが、使う前にいくつか考慮する点があります。

前方一致と後方一致は属性値全体でチェックされる

「どういうこと?」と思うところですが、次の例をご覧ください。

<style>
  [class^="content"] {
    color: red;
  }
</style>
<h2 class="title content-main">タイトル</h2>
<div class="meta content-sub">カテゴリー</div>
<div class="content">この記事のコンテンツがここに入ります。</div>

3つすべてのdivタグにcontentから始まるクラス名が含まれているので、すべて文字色が赤になると思われますが、実は1つしかスタイルは反映されません。
content~ってクラス名と前方一致してるじゃないか!」と思いますが、タグに設定された属性値全体と前方一致しているかどうかでチェックされます。
つまり、[class^="content"]だったらclass="content~"で始まらないと一致したとみなさないよ、ということです。
「前方一致/後方一致でスタイルを指定してるのに、なぜか効かない💦」ということも・・・。
どのようになるか、実際の表示をご覧ください。

See the Pen Example of Prefix Match by CSS by mimihokuro (@mimi_hokuro) on CodePen.

上記の例ですべてにスタイルを当てたい場合は部分一致(*=)で指定するか、属性値の並び順を変える必要があるので、使う場面には見極めが必要です。

パフォーマンスの問題

部分一致セレクタは非常に便利なのですが、コード量の多い大規模なDOM構造に対して使用する場合は、パフォーマンスにも注意が必要です。
特に*=セレクタは、すべての要素をチェックするため、処理が重くなることがあります。
例えば、DOMが100個でCSSルールが50個あった場合、100×50=5,000回のマッチング処理が行われることになります😱

優先度の問題

部分一致セレクタは、他のセレクタと組み合わせて使用することができますが、優先度に注意が必要です。
優先度が高いセレクタがある場合、部分一致セレクタが期待通りに機能しないことがあります。
優先度は、IDセレクタが最も高く、次にクラスセレクタ、そして最後にタグセレクタの順で優先されます。

さいごに

いかがでしたでしょうか??
部分一致はちょっとしたときに便利なんですが、ビシッと指定しないと「こんなとこに何でこのスタイルが!?」ということも十分にあり得るので、部分一致は最終手段程度に考えてもらえるといいかな思います👍

Posted in CSS

Chakra UIの横並び・縦並びしたいとき使うStack(HStack・VStack)・Flexの違いと使い分け

UI・コンポーネントライブラリはWebアプリを作るときに、開発はしたいけどデザインに苦手意識を持っていてなかなか進まない、そんなときに便利な存在ですが、Reactを使う人の中には「Chakra UI」を使っている人も多いんじゃないでしょうか?

ただ、Chakra UIを使い始めた人が気になるであろう点があります。

それが「Stack系の種類の多さ」と「Flexコンポーネントとの違い」です。

今回はそんな似たようなコンポーネントの違いと使い分けについてみていきたいと思います!

そもそもChakra UIって?

Chakra UIはアクセシビリティを重視したコンポーネントライブラリで、2024年4月に改正された障害者差別解消法に対するアクセシビリティ対応に有効とされるライブラリの一つです。

豊富なコンポーネントが用意されていて、レスポンシブ対応も行われている使いやすくなっています。

[

Chakra UI – A simple, modular and accessible component library that gives you the building blocks you need to build your React applications.

Simple, Modular and Accessible UI Components for your React Applications. Built with Styled System

v2.chakra-ui.com

](https://v2.chakra-ui.com/ "Chakra UI – A simple, modular and accessible component library that gives you the building blocks you need to build your React applications.")

Chakra UIにはレイアウトを組むためのコンポーネントがいくつも用意されていて、その中の一つにStackFlexがあります。

Stackとは?

Web制作でCSSを使っている人にはFlexコンポーネントの使い方は説明を見なくてもなんとなくイメージできると思いますが、Stackコンポーネントって聞きなじみがないかもしれません。

Chakra UIの公式ドキュメントにはこんな説明が。

Stack is a layout component used to group elements together and apply a space between them.

スタックは、要素をグループ化し、それらの間にスペースを適用するために使用されるレイアウトコンポーネントです。(DeepL訳)

Chakra UI公式ドキュメント「Stack」コンポーネント

つまり、StackFlexのように横並びや縦並びをさせたいときに使うコンポーネントです。

StackとFlexってどう違うの?

StackFlexも横並びや縦並びをしたいときに使うコンポーネントと説明しましたが、じゃあどう違うん?どう使い分ければええの?って思いますよね?

まずはそれぞれの特徴を見ていきましょう。

Stack(HStack、VStack)

Stackコンポーネントには、StackHStackVStackの3種類が用意されています。

HStackVStackはそれぞれ横並びや縦並びのために特化した、言わばショートカットのようなコンポーネントです。

HStackは子要素を横並びに、StackVStackは子要素を縦並びに配置します。

StackVStackも同じじゃん!と思うかもしれませんが、そこはショートカットたる所以と言いますか、デフォルトでStackは左寄せ、VStackは中央寄せになります。(HStackも横並びのまま、垂直方向に中央寄せとなります。)

Flex

Flexコンポーネントは言わずもがな、デフォルトで横並びになるコンポーネントです。

ただStackと異なるのは、使えるプロパティが違うという点とデフォルトでの子要素間の余白です。

例えば、Stack系では子要素間の余白を指定するspacing属性(CSSでいうgapプロパティ)が使えますが、Flexでは使えません。

逆にFlexではflexレイアウト専用のプロパティのショートハンドが用意されていて、flexDirectionならdirectionflexWrapならwrapといった、属性を省略して指定することができます。

違いがよくわからんのだが?

ここまで説明を見るとそれぞれのコンポーネントの違いがあまりないように感じますね。

それではどう使い分けるといいのでしょうか?

Chakra UIの公式ドキュメントにはこんなことが書いてあります。

The Stack component and the Flex component have their children spaced out evenly but the key difference is that the Stack won’t span the entire width of the container whereas the Flex will. Another thing to note is that the items in both Stack and Flex are aligned in the center by default.


StackコンポーネントとFlexコンポーネントは、子コンポーネントの間隔が均等ですが、重要な違いは、Stackがコンテナの幅いっぱいに配置されるのに対し、Flexはコンテナの幅いっぱいに配置されないことです。もうひとつ注意すべき点は、StackとFlexのアイテムはどちらもデフォルトで中央に配置されていることだ。(DeepL訳)

Chakra UI公式ドキュメント「Stack」コンポーネントより

Flex and Spacer vs Grid vs Stack#

The Flex and Spacer components, HStack treat children of different widths differently.

  • In HStack, the children will have equal spacing between them but they won’t span the entire width of the container.
  • With Flex and Spacer, the children will span the entire width of the container and also have equal spacing between them.

フレックスとスペーサーとグリッドとスタックの比較

FlexとSpacerコンポーネント、GridとHStackでは、異なる幅の子コンポーネントの扱いが異なります。

HStackでは、子コンポーネントの間隔は等しくなりますが、コンテナの幅全体には及びません。
Gridでは、子要素の始点の間隔は等しくなりますが、子要素間のギャップは等しくなりません。
FlexとSpacerを使用すると、子要素はコンテナの幅全体に広がり、子要素間の間隔も等しくなります。(DeepL訳)

Chakra UI公式ドキュメント「Flex」コンポーネントより

引用が長くなってしまいましたが、つまりFlexではSpacerという子要素間の余白を自動調整するコンポーネントと一緒に使うと、子要素が親要素の幅いっぱいまで広がって配置されて、Stackでは幅いっぱいまで広がらない、ということでした。

それ(Spacer)、Stackにやらせてください

が、一つ疑問に浮かぶ方もいるかもしれません。

そう、FlexSpacerをセットで、というのなら、StackSpacerをセットでは使えないのか?というところ。

実際のところ・・・使えます。

Chakra UIの公式ドキュメントにはお試し機能があるので、ぜひ下のコードをコピペして試してみてください。

import { Stack, HStack, Flex, Spacer, Box } from '@chakra-ui/react';

export const App = () => {
  return (
    <Stack spacing={4} px={4} py={16}>
      <HStack spacing='0' h={100} border="1px">
        <Box w='40px' h='40px' bg='yellow.200'>
          1
        </Box>
        <Box w='40px' h='40px' bg='tomato'>
          2
        </Box>
        <Spacer />
        <Box w='40px' h='40px' bg='pink.100'>
          3
        </Box>
      </HStack>
      <Flex border="1px" h={100} align="center">
        <Box w='40px' h='40px' bg='yellow.200'>
          1
        </Box>
        <Box w='40px' h='40px' bg='tomato'>
          2
        </Box>
        <Spacer />
        <Box w='40px' h='40px' bg='pink.100'>
          3
        </Box>
      </Flex>
    </Stack>
  )
}

ttps://play.chakra-ui.com

サンプルコードではHStackFlexを使って横並びにしていますが、全く同じ見た目を再現できており、StackでもしっかりSpacerが使えています。

ただ、HStackにはデフォルトでgapプロパティが付与されるようになっているので、余白なしで配置したい場合には打消しのための属性指定が必要なので少し冗長になってしまいますので、その場合はFlexを使うといいでしょう。

結論

FlexStackの違いについてみてきましたがどうでしょうか?

どの場面でどれを使っても同じように再現はできるので、ここではコレ!という決まりはありません。

ですが、コンポーネントによってスタイルの打消しが必要だったり、重複したりする場合もあるので、コードが煩雑にならないように気を付けて使っていきましょう。

HTML+CSSだけでマスク(切り抜き)したいときに参考にしたいテクニック3選

Webデザインをする上でやりたくなるテクニックの一つに切り抜き(マスク)があります。

文字や好きなシェイプの形で背景を切り抜いたりすると、華やかさというかなんかオシャレに見えるんですよね。

今回は色んな切り抜きのテクニックをご紹介します。

テキストの色にグラデーションをかける

テキストは通常では単色でしか指定できず、グラデーションがかけられません。

でもCSSでプロパティーをちょちょいと加えるだけで簡単にグラデーションがかけられるようになります。

<div class="gradation bg-clip">
  Lorem ipsum dolor sit, amet consectetur adipisicing elit.
</div>
.gradation {
  // 好きな色でグラデーション
  background: linear-gradient(30deg, #090979, #090979, #00d4ff, #090979, #090979);
}

.bg-clip {
  background-clip: text;
  color: transparent;
}

これ一つでもサイトの印象がガラリと変わりますね。

解説

テキストにグラデーションをかけるテクニックは、テキスト自体の色をグラデーションに変えているわけではなく、背景にグラデーションをかけてそれをテキストの形で切り抜き(マスク)をしています。

仕組みとしてはbackground-clip: text;で背景を前面にあるテキストの形で切り抜きをして、color: transparent;でテキストを透明にして背景の色を見えるようにしている、というカタチです。

ちょっと応用

グラデーションが動いてキラキラしてたらもっと目を引く演出になりそうじゃないですか?

ということで背景のグラデーションを動かしてみます。

.move {
  background-size: 300% 100%;
  background-position: 50% 50%;
  animation: move-background 1.5s infinite ease-in-out;

  @keyframes move-background {
    0% {
      background-position: 0% 50%;
    }
    100% {
      background-position: 100% 50%;
    }
  }
}

背景のサイズを大きくしてアニメーションで左から右へ移動させるようにしています。

より光沢のような高級感が出せていると思います。

実際の動きはこちらで見てみてください。

See the Pen background-clip: text; by mimihokuro (@mimi_hokuro) on CodePen.

SVGで切り抜き

次はSVG画像の形に切り抜く方法をご紹介します。

まずは実際のデモをご覧ください。

See the Pen clip-path by mimihokuro (@mimi_hokuro) on CodePen.

これの何がいいかって、「SVG」で切り抜いているところですよね。

SVGはベクター形式なので拡大縮小に強いのでキレイに切り抜けるところがいいところです。

スクロール量に合わせて拡大して次のコンテンツを見せる、みたいな使い方もできるので使いこなせれば表現の幅もグッと広がりますね。

SVGでの切り抜き方法には主に2つのパターンがあります。

  • clip-pathプロパティー+clipPathタグを使った方法
  • mask系プロパティー+maskタグを使った方法

clip-pathプロパティー+clipPathタグを使った方法

<div class="clip-path">
  <img src="https://picsum.photos/seed/picsum/300/300" alt="">
  <svg viewBox="0 0 512 512" width="0" height="0">
    <clipPath id="svg" clipPathUnits="objectBoundingBox">
      <path d="M378.409,0H208.294h-13.176l-9.314,9.315L57.017,138.101l-9.314,9.315v13.176v265.513   c0,47.36,38.528,85.896,85.895,85.896h244.811c47.361,0,85.888-38.535,85.888-85.896V85.896C464.297,38.528,425.77,0,378.409,0z M432.493,426.104c0,29.877-24.214,54.091-54.084,54.091H133.598c-29.877,0-54.091-24.214-54.091-54.091V160.592h83.717 c24.884,0,45.07-20.179,45.07-45.071V31.804h170.114c29.87,0,54.084,24.214,54.084,54.091V426.104z" />
      <path d="M180.296,296.668l-4.846-0.67c-10.63-1.487-14.265-4.978-14.265-10.104c0-5.78,4.309-9.817,12.383-9.817   c5.653,0,11.305,1.62,15.745,3.764c1.886,0.942,3.903,1.487,5.789,1.487c4.845,0,8.612-3.63,8.612-8.616   c0-3.226-1.481-5.921-4.71-7.939c-5.384-3.372-15.476-6.06-25.572-6.06c-19.781,0-32.436,11.171-32.436,27.998   c0,16.15,10.232,24.898,28.938,27.454l4.846,0.67c10.903,1.48,14.129,4.846,14.129,10.229c0,6.326-5.247,10.766-14.939,10.766 c-6.727,0-12.111-1.745-19.645-5.921c-1.616-0.942-3.634-1.62-5.788-1.62c-5.115,0-8.885,3.91-8.885,8.756 c0,3.226,1.616,6.326,4.713,8.344c6.054,3.764,15.878,7.8,28.798,7.8c23.823,0,35.934-12.24,35.934-28.795   C209.097,307.84,199.273,299.356,180.296,296.668z" />
      <path d="M281.108,259.382c-4.577,0-7.939,2.43-9.556,7.674l-16.69,54.51h-0.402l-17.634-54.51   c-1.745-5.244-4.978-7.674-9.551-7.674c-5.653,0-9.692,4.176-9.692,9.287c0,1.347,0.269,2.834,0.67,4.175l23.286,68.104   c2.96,8.477,6.727,11.57,12.652,11.57c5.785,0,9.555-3.093,12.516-11.57l23.282-68.104c0.406-1.341,0.674-2.828,0.674-4.175   C290.664,263.558,286.76,259.382,281.108,259.382z" />
      <path d="M364.556,300.836h-18.841c-5.114,0-8.344,3.1-8.344,7.806c0,4.713,3.23,7.814,8.344,7.814h6.193   c0.538,0,0.803,0.258,0.803,0.803c0,3.505-0.265,6.598-1.075,9.014c-1.882,5.796-7.67,9.426-14.669,9.426   c-7.943,0-12.921-3.903-14.939-10.096c-1.075-3.365-1.48-7.8-1.48-19.648c0-11.842,0.405-16.15,1.48-19.516   c2.018-6.325,6.867-10.228,14.67-10.228c5.924,0,10.362,1.885,13.859,6.724c2.695,3.777,5.387,4.852,8.749,4.852   c4.981,0,9.021-3.638,9.021-8.888c0-2.151-0.674-4.035-1.752-5.921c-4.842-8.204-15.071-14.264-29.877-14.264   c-16.287,0-28.935,7.408-33.644,22.204c-2.022,6.466-2.559,11.576-2.559,25.038c0,13.454,0.538,18.573,2.559,25.031   c4.709,14.802,17.357,22.204,33.644,22.204c16.286,0,28.668-8.204,33.374-22.881c1.617-5.111,2.29-12.645,2.29-20.716v-0.95   C372.362,303.664,369.538,300.836,364.556,300.836z" />
    </clipPath>
  </svg>
</div>
.clip-path {
  width: 300px;
  height: 300px;
  clip-path: url(#svg);

  img {
    width: 100%;
    height: 100%;
  }

  clipPath {
    transform: scale(0.00195);
  }
}

解説

まずHTMLの方では、imgタグで指定した画像が切り抜かれたときの背景となり、svgタグ内で指定したパスで実際に切り抜きを行うんですが、ポイントは2つあります。

  • svgパスをclipPathタグで囲う
  • clipPathタグにclipPathUnits属性を指定する

clipPathタグ自体は、囲ったパスを切り抜きに使うことを定義するためのもので、clipPathUnits属性は描画する範囲を指定しています。今回はobjectBoundingBoxを指定していますが、この場合はclipPathで囲うパスのサイズに合わせて描画します。

ここで注意なのがパスのサイズ

そのままだと元々のSVG画像のサイズで切り抜きしようとしてしまうので、元のサイズがどデカいとデカすぎて切り抜きされてるのにされてないと錯覚してしまうこともしばしば。

そのため、clipPathタグに対してtransform: scale; で縮小している、というわけです。

ここで指定している値は決まったものではなく、SVG画像のviewboxのサイズによって変動します。

値の出し方としては、1 ÷ viewboxの値という式になり、デモで使っているSVG画像のサイズの場合、1 ÷ 512 ≒ 0.00195で指定することでちょうどいいサイズになります。

≒としたのは、実際計算すると0.001953125となります。viewboxサイズによってはもっと細かい数値になることもあるかもしれず、正確に指定してもいいですが、省略した場合との差は微々たるものなのでここでは省略しています。正確に指定するかある程度で省略するかは、チームや会社の方針などに従って決めてください。

mask系プロパティー+maskタグを使った方法

<svg class="mask" viewBox="0 0 512 512" x="0" y="0">
  <image href="https://picsum.photos/seed/picsum/300/300"></image>
  <mask id="customMask">
    <path d="M378.409,0H208.294h-13.176l-9.314,9.315L57.017,138.101l-9.314,9.315v13.176v265.513   c0,47.36,38.528,85.896,85.895,85.896h244.811c47.361,0,85.888-38.535,85.888-85.896V85.896C464.297,38.528,425.77,0,378.409,0z M432.493,426.104c0,29.877-24.214,54.091-54.084,54.091H133.598c-29.877,0-54.091-24.214-54.091-54.091V160.592h83.717 c24.884,0,45.07-20.179,45.07-45.071V31.804h170.114c29.87,0,54.084,24.214,54.084,54.091V426.104z" />
    <path d="M180.296,296.668l-4.846-0.67c-10.63-1.487-14.265-4.978-14.265-10.104c0-5.78,4.309-9.817,12.383-9.817   c5.653,0,11.305,1.62,15.745,3.764c1.886,0.942,3.903,1.487,5.789,1.487c4.845,0,8.612-3.63,8.612-8.616   c0-3.226-1.481-5.921-4.71-7.939c-5.384-3.372-15.476-6.06-25.572-6.06c-19.781,0-32.436,11.171-32.436,27.998   c0,16.15,10.232,24.898,28.938,27.454l4.846,0.67c10.903,1.48,14.129,4.846,14.129,10.229c0,6.326-5.247,10.766-14.939,10.766 c-6.727,0-12.111-1.745-19.645-5.921c-1.616-0.942-3.634-1.62-5.788-1.62c-5.115,0-8.885,3.91-8.885,8.756 c0,3.226,1.616,6.326,4.713,8.344c6.054,3.764,15.878,7.8,28.798,7.8c23.823,0,35.934-12.24,35.934-28.795   C209.097,307.84,199.273,299.356,180.296,296.668z" />
    <path d="M281.108,259.382c-4.577,0-7.939,2.43-9.556,7.674l-16.69,54.51h-0.402l-17.634-54.51   c-1.745-5.244-4.978-7.674-9.551-7.674c-5.653,0-9.692,4.176-9.692,9.287c0,1.347,0.269,2.834,0.67,4.175l23.286,68.104   c2.96,8.477,6.727,11.57,12.652,11.57c5.785,0,9.555-3.093,12.516-11.57l23.282-68.104c0.406-1.341,0.674-2.828,0.674-4.175   C290.664,263.558,286.76,259.382,281.108,259.382z" />
    <path d="M364.556,300.836h-18.841c-5.114,0-8.344,3.1-8.344,7.806c0,4.713,3.23,7.814,8.344,7.814h6.193   c0.538,0,0.803,0.258,0.803,0.803c0,3.505-0.265,6.598-1.075,9.014c-1.882,5.796-7.67,9.426-14.669,9.426   c-7.943,0-12.921-3.903-14.939-10.096c-1.075-3.365-1.48-7.8-1.48-19.648c0-11.842,0.405-16.15,1.48-19.516   c2.018-6.325,6.867-10.228,14.67-10.228c5.924,0,10.362,1.885,13.859,6.724c2.695,3.777,5.387,4.852,8.749,4.852   c4.981,0,9.021-3.638,9.021-8.888c0-2.151-0.674-4.035-1.752-5.921c-4.842-8.204-15.071-14.264-29.877-14.264   c-16.287,0-28.935,7.408-33.644,22.204c-2.022,6.466-2.559,11.576-2.559,25.038c0,13.454,0.538,18.573,2.559,25.031   c4.709,14.802,17.357,22.204,33.644,22.204c16.286,0,28.668-8.204,33.374-22.881c1.617-5.111,2.29-12.645,2.29-20.716v-0.95   C372.362,303.664,369.538,300.836,364.556,300.836z" />
  </mask>
</svg>
.mask {
  width: 300px;
  height: 300px;

  image {
    width: 100%;
    mask-image: url(#customMask);
    mask-size: cover;
    mask-position: center;
  }

  path {
    fill: #ffffff;
  }
}

解説

簡単に言うと、imageタグで背景としたい画像を設定、maskタグで切り抜きしたいSVGパスを指定します。

CSSではmask-imageプロパティで切り抜きしたい対象のSVG画像を指定、mask-sizemask-positionでサイズと位置を指定しています。

ここではSVGのパスにfillstrokeを指定しないと切り抜きしてくれないので忘れずに指定しましょう。

ポイント

ここでのポイントとしては、画像指定に使うタグはimgタグではなく、imageタグであるというところ。

imageタグはSVGにだけ使える特殊なタグで、今回のmaskプロパティーとSVGを使った切り抜きの場合には、svgタグの配下に入れないと機能しません。

imageタグについての詳細はMDNをご参照ください。

[

– SVG | MDN

The は SVG の要素で、 SVG 文書内に画像を含めます。これはラスター画像ファイルや他の SVG ファイルを表示することができます。

developer.mozilla.org

](https://developer.mozilla.org/ja/docs/Web/SVG/Element/image " – SVG | MDN")

画像を縦横サイズ関係なく任意の比率で切り抜き

お次は画像を引き延ばしせずに、縦長・横長・正方形など好きな比率で切り抜くテクニックです。

これまたどういうこっちゃという方に、デモご用意しました。

See the Pen object-fit by mimihokuro (@mimi_hokuro) on CodePen.

すべて同じ画像を使っていて、真ん中と右の画像ではCSSで一部だけ切り抜いています。

コードの抜粋はこちら

<div class="object-fit">
  <img src="https://picsum.photos/id/20/500/300">
</div>

<div class="object-view-box">
  <img src="https://picsum.photos/id/20/500/300">
</div>
.object-fit img {
  width: 200px;
  height: 300px;
  object-fit: cover;
  object-position: 30% 10%;
}

.object-view-box img {
  object-view-box: inset(100px 50px 30px 50px);
}

解説

ポイントとしては、切り抜きたい画像にobject-fitプロパティーとサイズを指定するだけです。

コードにはobject-positionプロパティーも指定されていますが、こちらは表示したい位置指定のものなので、必要に応じて使いましょう。

object-view-boxプロパティーでは元のサイズの上下左右からどれだけの範囲を表示するかを指定しています。

こんなシーンで

レスポンシブ対応で、画像の表示方法についてよくある問題として挙がります。PCとスマホでは画面比率が違うので、PCで表示していた画像をそのままスマホで表示すると小さくなりすぎて見づらかったり、はたまたスマホでは同じ画像の一部だけ表示したいから複数画像を用意するほどでもない、など考えなければならないことがあります。

object-fitでは指定のサイズで切り抜けるだけでなく、画面幅に合わせることもできるので煩わしい設定をする必要がなくなります。

こちらのデモを、スマホかデベロッパーツールでスマホモード、もしくはブラウザサイズの横幅を縮めてみてください。

See the Pen Untitled by mimihokuro (@mimi_hokuro) on CodePen.

縦幅は画面いっぱいのまま、画像のサイド部分が切り抜かれています。

サイトのファーストビューやインパクトを出したい箇所にはうってつけの方法だと思います。

最後に

いかがでしょうか?

マスク(切り抜き)は奥が深く、なかなかに複雑ですが、使いこなせれば表現の幅はグッと広がります。

今回の記事がその助けになれば幸いです。

シンプル、だけどレスポンシブな日本語テキストの改行テクニック

改行の入る箇所によって、キャッチコピーとか言葉の伝わりやすさや印象というのは変わってきます。

でもWebサイトでは、日本語というのは英語よりも改行が入れにくいものです。

というのも単語ごとにスペースで区切る英語と違って、日本語は単語ごとにスペースで区切ることがないので、基本的にブラウザは区切る箇所がわからないので単語の途中だろうが問答無用で改行することがよくあります。

今回はレスポンシブで任意の箇所で改行させるためのテクニックをご紹介します。

まずはデモで

See the Pen
line-breaks-in-japanese-text
by mimihokuro (@mimi_hokuro)
on CodePen.

それぞれのコンテンツ幅は拡大縮小できるので、テキストがはみ出る具合や改行のタイミングなど試してみてください。

それでは解説です。

シンプルな【display: inline-block】を使った改行

私の感覚ではよく使われている印象を受ける方法ですが、display: inline-block;spanを組み合わせて改行させる方法です。

<p>
  <span>誰だって、</span><span>ほんとうにいいことをしたら、</span><span>いちばん幸せなんだねぇ。</span>
</p>
span {
  display: inline-block;
}

文章は「銀河鉄道の夜」より一部抜粋

この方法は今回ご紹介する中でもシンプルで直感的に使えるので使いやすいかと思います。

でも見ての通り改行するブロックごとにspanでいくつも囲ってブロック分けするのでコードが煩雑になりがちなので見づらくなるのがネックです。

句読点で改行する【word-break: keep-all】

次に句読点を改行ポイントとして自動で認識して改行してくれる方法です。

<p class="word-break">誰だって、ほんとうにいいことをしたら、いちばん幸せなんだねぇ。</p>
.word-break {
    word-break: keep-all;
}

句読点の後に改行が自動で入る

ムダにタグが増えないし句読点で改行してくれるならこれでいいんじゃない?と思うかもしれませんが、一つ問題があって、テキストが要素よりも長い場合は改行されずに要素を突き抜けて表示されちゃうんです。

改行されずにテキストが要素からはみ出てしまう

幅に合わせて改行する【wbr】

word-break: keep-all;にHTMLで改行タグであるwbrを組み合わせることで、要素幅に対してテキストがはみ出そうになったときにwbrを入れた箇所で改行させることができます。

<p class="word-break">誰だって、ほんとうに<wbr>いいことをしたら、いちばん<wbr>幸せなんだねぇ。</p>

テキストが要素からはみ出さずを配置した箇所で改行される

しかしまだ問題は残っています。

wbrで改行はされるようになりましたが、wbrがない箇所でははみ出してしまう問題が解消されていません。

wbrを細かく設定すればそこまで気にしなくてもいいんですが、コードの煩雑になりやすくなったり、スマホのような画面幅が狭いデバイスだと意図しない表示がされてしまう可能性があります。

overflow-wrap: anywhere;でさらに細かい改行

今までは句読点やwbrで明示的に改行させましたが、それ以外の箇所では改行してくれないのでさらに1行追加して細かい調整をします。

CSSにoverflow-wrap: anywhere;を追加することで、句読点でもwbrでも一文字単位でも改行してくれます。

<p class="word-break overflow-wrap">誰だって、ほんとうに<wbr>いいことをしたら、いちばん<wbr>幸せなんだねぇ。</p>
.word-break {
    word-break: keep-all;
}

.overflow-wrap {
    overflow-wrap: anywhere;
}

じゃあ全部これでやればいいじゃん?と思いますが、これも細かい問題がまだあって、一文字単位で改行する特定のせいで句読点の前でも改行されちゃんです。

作文を思い浮かべると分かりやすいと思うんですが、日本語というのは一行の最初に句読点が来るのはNGで、前行の最後のマスに一緒に書く法則があります。

Webでも通常は、その法則のように句読点が行の初めに来ないよう句読点の直前の一文字と一緒に改行されますが、今までの方法を使うとすべて無視してしまいます。

それぞれにメリット・デメリット。結論、どうすればいいの?

結論から言うと、適材適所、です。

使い分けるなら、説明文のような長い文章の場合はデフォルトもしくはword-break: break-all;を使い、見出しやキャッチコピーなど途中で改行をさけたいメッセージ性の強い箇所では今回紹介した方法を使うのがいいんじゃないかなと思います。

word-break: break-all;は要素からテキストがはみ出そうな場合に、単語の途中でも自動で改行させるためのプロパティーです。デフォルトでも改行してくれるんですが日本語だけの話で、英単語は途中で改行してくれません。word-break: break-all;を使うことで英単語の途中でも改行してくれるので、長い単語でもはみ出さずに改行させることができます。

場合によってはあえて改行させない方がいい場合もあるので組み合わせて使ってみてください。

YouTube埋め込みの最適解は?Webデザイナーが知っておくべき「埋め込み方法のベストプラクティス」と「縦型動画(ショート動画)」の導入の技術的ポイント

こんにちは、みみほくろです。

Youtubeって面白い動画が多くて時間を忘れちゃいますよね。

自分の動画もみんなに見てほしい!ってことで自分のサイトにYoutube動画を設置することもあると思います。

ですが、YouTube動画を埋め込む際、単にコードを貼り付けるだけでなく、「ページの表示速度(Lighthouseスコア)」や、近年主流となっている「YouTubeショート(縦長動画)」への対応は、UX(ユーザー体験)に直結する重要な要素なため、適材適所を見極める必要があります。

今回は、主要な3つの実装方法について、それぞれのメリット・デメリットを詳しく解説します。

紹介する実装方法はこの3つです。

  • Youtube発行のIframeをそのまま貼り付け
  • DOM操作による埋め込み
  • Youtube Player API

それでは一つ一つ見ていきましょう!

標準的な埋め込み:「公式Iframe」

YouTubeの共有機能から取得した埋め込みコードをそのままHTMLに配置する、手っ取り早くてスタンダードなやり方です。

赤枠の「共有」ボタンから発行されます。(画像はYoutube公式サイトで使われているYoutube動画のキャプチャ)

メリット:圧倒的な導入スピードと安定性

  • 実装が容易: HTMLを1行貼り付けるだけで完了し、プログラミングの知識がなくても対応可能です。
  • メンテナンス性: YouTube側の仕様変更があっても、公式が提供するコードであるため壊れにくく、保守が容易です。

デメリット:ページパフォーマンスへの悪影響

  • レンダリングブロック: ブラウザはIframe内のリソースを読み込むためにメインスレッドを占有し、ページの初期表示を遅延させます。
  • Lighthouseスコアの低下: 動画が重い場合、LCP(最大視覚コンテンツの表示時間)などのスコアに悪影響が出てしまい、SEO面でのマイナス要因になり得ます。

パフォーマンス重視:「DOM操作」による遅延読み込み

ユーザーが「再生ボタン」を押すまで動画を読み込まない、あるいはCSSや画像などページ全体の読み込みが完了した後にIframeを生成してHTMLに追加する手法です。

メリット:初期表示速度の劇的な改善

  • リクエストの削減: ページロード時にYouTube関連の重いスクリプトや画像(サムネイル以外)を読み込まないため、Lighthouseスコアを高く維持できます。
  • ユーザーファースト: 「動画を見たい」という明確な意思表示(クリック)があって初めて通信が発生するため、モバイルユーザーのデータ通信量節約にも貢献します。

デメリット:ユーザーの手間の増加

  • 2ステップの操作: 「動画読み込みボタンを押す」→「動画の再生ボタンを押す」という2段階の操作が必要になる場合があり、直感的なUXを損なうリスクがあります。
  • JavaScript依存: スクリプトがオフの環境では動画が全く表示されないため、フォールバックの検討が必要です。

実装例:

<button id="createYoutubeButton">動画を読み込む</button>
<div class="youtube-container"></div>

<script>
const youtubeContainer = document.querySelector(".youtube-container");
const createYoutubeButton = document.querySelector("#createYoutubeButton");

createYoutubeButton.addEventListener("click", () => {
    youtubeContainer.innerHTML = `<iframe src="https://www.youtube.com/embed/M7lc1UVf-VE" title="YouTube video player" frameborder="0" allowfullscreen></iframe>`;
});
</script>

読み込んでいるYoutube動画は公式で紹介しているものを使っています。

3. 高度な制御:「YouTube Player API」

JavaScriptでプレーヤーの挙動を詳細にコントロールする、開発者向けの手法です。

メリット:リッチなUXと細かい挙動制御

  • 細かなパラメータ管理: 再生終了時に特定の処理を走らせる、特定の時間から再生を開始する、といった柔軟な制御が可能です。
  • 非同期読み込み: API自体が非同期で読み込まれるため、標準のIframe貼り付けよりもパフォーマンスへの影響を抑えつつ、高度な機能を提供できます。

デメリット:実装コストと複雑性

  • 学習コスト: APIの仕様を理解する必要があり、単純な埋め込みに比べてコード量が増え、デバッグの手間も発生します。
  • 外部スクリプトへの依存: YouTube側のAPIサーバーが万が一ダウンしたり、スクリプトの読み込みに失敗したりした場合、プレーヤーが正しく初期化されないリスクがあります。

実装手順の詳細

YouTube Player APIを導入するための具体的なステップは以下の通りです。

① APIスクリプトの非同期読み込み

まず、APIの本体となるJavaScriptファイルを動的に読み込んでDOM上に組み込みます。

// APIのスクリプトタグを生成
const tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";

// 最初のscriptタグの前に挿入
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

② プレーヤーの初期化

APIの読み込みが完了すると、グローバル関数 onYouTubeIframeAPIReady が自動的に実行されます。この中でプレーヤーのインスタンスを生成します。

let player;
function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', { // HTML側のIDを指定
        height: '360',
        width: '640',
        videoId: 'M7lc1UVf-VE',
        playerVars: {
            'playsinline': 1, // iOSでインライン再生を許可
            'rel': 0          // 関連動画を自身のチャンネルに限定
        },
        events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
        }
    });
}

playerVarsでは動画の状態を設定する「パラメータ」を指定することができます。よくあるパラメータは後述していますので、そちらを参考にするか、Youtube Player APIの公式ページをご覧ください。

[

YouTube Player API Reference for iframe Embeds  |  YouTube IFrame Player API  |  Google for Developers

アプリに YouTube プレーヤーを埋め込みます。

developers.google.com

](https://developers.google.com/youtube/iframe_api_reference?hl=ja "YouTube Player API Reference for iframe Embeds  |  YouTube IFrame Player API  |  Google for Developers")

③ イベントによる制御

動画の準備が整ったときや、再生状態が変わったとき(再生・停止・終了)に独自の処理を挟むことができます。

// プレーヤーの準備が整ったとき
function onPlayerReady(event) {
    // 例:準備ができたら自動でミュートにして再生
    event.target.mute();
    event.target.playVideo();
}

// 状態が変化したとき
function onPlayerStateChange(event) {
    if (event.data == YT.PlayerState.ENDED) {
        console.log("動画の再生が終了しました。");
        // 次の動画へ遷移させる、などの処理が可能
    }
}

挙動を制御する「プレーヤーパラメータ」の活用

Youtube動画にはURLの末尾にパラメータを付与することで、動画の挙動をカスタマイズすることができます。

よく使うパラメータ一覧

パラメータ

内容

autoplay

1

自動再生する。

mute

1

消音状態で再生する(自動再生には必須)。

controls

0 / 1

プレーヤーのコントロールを表示するか。

loop

1

ループ再生する(playlistパラメータとの併用が必要)。

rel

0

再生終了時、同じチャンネル内の関連動画のみを表示する。

start

数字

再生を開始する秒数を指定する。

end

数字

再生を終了する秒数を指定する。

具体的な使用例

① 背景動画として「ループ再生」させる

環境映像などを背景として使う場合、音声を消し、コントロールを隠してループさせます。

loop=1を使う際は、playlistパラメータに同じ動画IDを入れる必要があります。

<iframe src="https://www.youtube.com/embed/VIDEO_ID?autoplay=1&mute=1&loop=1&playlist=VIDEO_ID&controls=0"></iframe>

② 動画の「見どころ」だけを再生する

長い動画の中で、特定の30秒間だけを見せたい場合などに有効です。

<!-- 60秒目から再生開始し、90秒目で終了する -->
<iframe src="https://www.youtube.com/embed/VIDEO_ID?start=60&end=90"></iframe>

実装時の注意点:自動再生のルール

現在のブラウザポリシーにより、autoplay=1 を指定する場合は必ず mute=1 をセットにする必要があります。音声が出る状態での自動再生は基本的にブロックされます。

【重要】通常動画とショート動画のレスポンシブ戦略

YouTubeショート(9:16)を埋め込む際は、通常の動画(16:9)とは異なる設定が必要です。

1. 埋め込み用URLへの変換

Youtubeショートには埋め込み用のコードがデフォルトでは用意されていないので、自分でカスタマイズする必要があります

  • 視聴用URL: https://www.youtube.com/shorts/VIDEO_ID
  • 埋め込み用: https://www.youtube.com/embed/VIDEO_ID

といってもshortsembedに変えるだけです笑

2. デバイスごとの最適なアスペクト比

モダンなCSSプロパティ aspect-ratio を活用します。

/* 動画共通のベース設定 */
.video-wrapper {
    position: relative;
    width: 100%;
    margin: 20px auto;
}

.video-wrapper iframe {
    width: 100%;
    height: 100%;
    border: none;
}

/* 通常動画 (16:9) */
.video-normal {
    aspect-ratio: 16 / 9;
    max-width: 800px;
}

/* ショート動画 (9:16) */
.video-shorts {
    aspect-ratio: 9 / 16;
    width: 100%;
    max-width: 400px;
}

/* PC向けの調整 */
@media screen and (min-width: 768px) {
    .video-shorts {
        max-width: 315px; 
    }
}

通常の動画では16:9、ショートの場合には9:16と切り替えることができます。

まとめ:要件に合わせた手法の選択

さて、ここまでYoutube動画の埋め込み方法をいくつかご紹介しましたが、下記のような使い分けがオススメです。

  • スピード最優先のスポット案件公式Iframe
  • Lighthouseスコアを改善したいサイトDOM操作による後読み
  • 複雑なインタラクションが必要なキャンペーンYouTube Player API
  • ショート動画URL変換とデバイスごとのサイズ管理を徹底する

ちなみにYoutube Player APIには40以上の関数と6つのイベントに20ほどのプロパティーが用意されているので、より細かい調整を行いたい場合にうってつけです。

なので、オススメとしてはYoutube Player APIですが、現場の要件に合わせて、ケースバイケースで使い分けてみてください。

要素をスクロールに合わせて表示・非表示させたり切り替える方法

最近スクロールで追従するヘッダーがスタンダードかってほど見かけるようになりました。

グローバルナビゲーションを常に表示させることでページのどこにいても見たいページにアクセスできて、ユーザーとしては欲しい情報を探しやすくサイト運営者としては回遊性を高めやすい手法だと思います。

でも追従するヘッダーって時にはユーザーの閲覧の邪魔になってしまうんですよね。

常にメインコンテンツの一部をヘッダーで隠していることになって、画面サイズの小さいノートPCやスマートフォンだと余計に見づらくなりやすく、メインコンテンツの魅力が十分に伝えられなかったり、見にくくてUXの悪化につながります。

そこで今回は、下スクロール時は非表示、上スクロール時に表示させるようなスクロールの向きに合わせて要素を変化させる方法をご紹介します。

この記事ではスクロールでヘッダーが上方向に隠れる仕様で説明しています。下左右へ隠れる仕様については応用の章のCodePenをご覧ください。

基本のコード

説明用なのでHTMLはかなりシンプルになっています。

<div class="header">
  スクロールで非表示
</div>

以下はJavaScriptです。

// 現在の位置を保持
let currentPosition = 0;

// ヘッダーの高さを取得
const header = document.querySelector(".header");
const headerHeight = header.clientHeight * -1;

window.addEventListener("scroll", () => {

  // スクロール位置を保持
  let scrollPosition = document.documentElement.scrollTop;

  // スクロールに合わせて要素をヘッダーの高さ分だけ移動(表示域から隠したり表示したり)
  if (currentPosition <= scrollPosition) {
    header.style.transform = "translate(0," + headerHeight + "px)";
  } else if (currentPosition > scrollPosition) {
    header.style.transform = "translate(0, 0)";
  }
  currentPosition = document.documentElement.scrollTop;
})

解説

まず現在の位置を0として定義し、スクロールごとに発生するイベントによってスクロール位置を取得、現在の位置とスクロール位置を比較しています。

現在の位置の数値に対してスクロール位置の数値が大きく(下スクロール)なればヘッダーを非表示に、逆に小さく(上スクロール)なればヘッダーを再表示する仕組みです。

今回はヘッダーの高さを明確に設定していないのでJavaScriptによってヘッダーの高さを動的に取得してCSSスタイルを操作する仕様にしていますが、ヘッダーのサイズが明確ならばクラスの付け外しで表示・非表示を切り替えてもいいかと思います。

応用編

応用では上下左右にスクロールで表示・非表示が切り替わる要素を配置しています。

See the Pen scroll to hide by mimihokuro (@mimi_hokuro) on CodePen.

さていかがでしたでしょうか?

スクロールに合わせて要素の変化させることは使いやすさだけでなく、使いようによってはユーザーの目を引く演出も実装できそうですね。

この記事が参考になれば幸いです~。

JavaScriptを使わず、たった2つのCSSスタイルを追加するだけで、簡単にスライダーを作る方法

記事コンテンツでもECでもブランドページでも、Webサイトには多くの情報を載せてユーザーに少しでも伝えたいことってありますよね。

そこで、限られた範囲に多くの情報を載せられるのがスライダー(カルーセル)です。

スライダーを実装するとき、よく使われるのがSlickやSwiperといったJavaScriptライブラリですが、使わないスタイルやメソッドも多いためサイトの表示速度遅延に影響を及ぼすことも。

今回はJavaScriptを使わずCSSだけでスライダーを作る方法をご紹介します。

この記事ではマウススクロールやフリックによるスクロールで動作するスライダーについて紹介しています。SwiperやSlickのようなボタンによるスワイプについては説明していませんのでご注意ください。

デモ

デモとして一度に表示する画像は1枚、横方向のシンプルなスライダーを用意しました。

See the Pen
Untitled
by mimihokuro (@mimi_hokuro)
on CodePen.

基本のコード

<div class="slider">
  <img src="https://placehold.jp/0aa864/ffffff/600x300.png">
  <img src="https://placehold.jp/0aa864/ffffff/600x300.png">
  <img src="https://placehold.jp/0aa864/ffffff/600x300.png">
</div>

HTMLでは画像にダミー画像生成のplacehold.jpで生成したものを使用したシンプルな構成になっています。

.slider {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  max-width: 400px;
  width: 100%;
  margin: auto;
  scroll-snap-type: x mandatory;
}

img {
  width: 100%;
  scroll-snap-align: center;
}

解説

今回は親要素にflexを指定して横並びに、表示域を幅400pxで制限して、はみ出す分はスクロールするようにしています。

追加スタイルその1:scroll-snap-type

ここで指定しているscroll-snap-typeが今回のポイントの1つです。

ところでスクロールスナップとは?という点ですが、MDNではこのように解説しています。

ユーザーが文書をスクロールする際に、特定の位置にスクロールをスナップさせる

MDN「CSS スクロールスナップの基本概念」より抜粋

ちょっとこれだけだと分かりづらいですが、特定の位置にピタッと移動(スクロール)させる動作、というと分かりやすいでしょうか?

このscroll-snapのおかげでCSSだけを使ってSwiperやSlickに似た動作をさせることができます。

前述しましたが、ここではあくまで、マウススクロールやフリックをしたときのスクロール動作についての話になります。SwiperやSlickのようなボタンクリックでスクロールさせるためにはJavaScriptが別途必要ですのでご注意ください。

サンプルコードのscroll-snap-typeには二つの値が指定されていますが、1つ目の値にはスクロールスナップを適用させる方向、2つ目の値にはスナップの度合いを指定します。

まずxがスクロールの方向になり、x軸に沿ったスクロール方向ということになります。

y軸に適用させたいならyを指定する、ということですね。

2つ目の値についてですが、mandatoryproximityのどちらかを指定することができます。

mandatoryはスナップをSwiperやSlickのような軽い操作感で演出してくれますが、それ故に簡単にスナップしてしまうので、ユーザーが見たい部分が見れずにスナップしてしまうなど、逆にユーザーをイラつかせてしまう可能性もあるので使用には慎重になる必要があります。

proximityは、スナップ地点が近くなるまでスクロールするとスナップされるため、mandatoryに比べて軽い操作感というわけにはいきませんがコンテンツを見逃してしまう可能性は低くなります。

と、つらつらと言葉を並べてきましたが言ってることが分かりづらいかと思いますので、百聞は一見に如かず、こちらのデモで使用感を見てください。

See the Pen
Difference between 〇 and △
by mimihokuro (@mimi_hokuro)
on CodePen.

追加スタイルその2:scroll-snap-align

scroll-snap-alignはどの位置をスナップの基準にするか指定できます。

startはスナップする範囲の先頭に、centerは中央、endは末尾にピタッと移動します。

こちらもデモを用意しました。

スナップ位置が分かりやすいよう、親要素よりも子要素を大きくはみ出した状態に設定しています。

See the Pen
scroll-snap-align
by mimihokuro (@mimi_hokuro)
on CodePen.

子要素の表示域を親要素に合わせるならどの値を指定しても問題ありません。

さていかがでしたでしょうか?

CSSにたった2つのスタイルを追加するだけでスライダーがJavaScriptなしで実装できてしまうなんて神かよ、と思いましたね。

この記事が参考になれば幸いです~。

空要素に:emptyでスタイルを指定したのになぜか効かない・・・。:emptyの意外な落とし穴

テキストも画像も入っていない空のHTML要素ってありますよね。

特にPHPのような動的に生成したHTMLでは、場合によって中身が空の要素が出てくることが多いと思います。

しかし、ムダな余白を作ったり親要素でFlexGridなどを指定していると意図しないレイアウト崩れを引き起こすこともしばしば。

そんな子要素を持たない空要素を非表示にしたり特定のスタイルを指定したいときに便利なのが:emptyという疑似クラスです。

:emptyとは?どんなときに使う?

前述した通り、親要素でFlexやGridなどを指定してレイアウトを組んでいる場合、子要素の一つが空だとムダな余白ができてしまいます。

例えばこんなスタイルを指定しているとします。

<div class="flex">
  <div class="child">子要素1</div>
  <div class="child">子要素2</div>
  <div class="child"></div> <!-- 子要素3は空 -->
  <div class="child">子要素4</div>
  <div class="child">子要素5</div>
</div>
.flex {
  display: flex;
  gap: 40px;
}

.flex div {
  padding: 16px;
  background-color: rgb(100,150,200);
  color: #ffffff;
}

flexを付与した親要素に横並びになった5つの子要素が含まれていますが、その内1つがテキストもなにもない空要素です。

この場合、空要素はどうなるでしょうか?

無視されて子要素が4つ横並びになるでしょうか?

残念ながら5つの子要素が横並びになり、空要素は背景色と余白を持って表示されてしまいます。

各子要素にpaddingを指定しているため、空要素にも余白を含んでしまう

ここで:emptyの出番です。

上記のコードに以下のスタイルを追加することで空要素は非表示になりムダな余白が生まれません。

.flex div:empty { // 空のdiv要素を指定
  display: none;
}

:emptyの落とし穴

ここからが今回の本題です。

見た目で空要素だから:empty使えばいいや!というのはちょっと待ってください。

以下の例を見てください。

<div class="flex">
  <div>子要素1</div>
  <div>子要素2</div>
  <div> </div> <!-- 子要素3は空? -->
  <div>
</div> <!-- 子要素4も空? -->
  <div>子要素5</div>
</div>

子要素に:emptyを指定するとどうなるでしょうか?

この場合子要素はすべて表示されてしまいます

実は:emptyは中身が完全に空の状態でしかスタイルを反映させることができません。

上記のコードの場合、子要素3は「空白」という要素を持っているため空要素とみなされません。

子要素4の改行も同様です。空白はなくとも「改行」という要素を持つことになり、空要素判定されず:emptyが効かなくなるのです。

CMSやASPなどで起こる問題

直接HTMLを編集して空白を削除すれば簡単なのですが、WordPressなどのCMSやfutureshopなどといったSaasやASPでは、動的にHTMLを生成されるため、場合によっては制御できずどうしても空白や改行が含まれてしまうことがあります。

そうなるとそのままでは:emptyが使えないので別の方法をとる必要がありますが、残念ながら今のところ:emptyに代わるものはなく、JavaScriptでクラスを付与するか直接DOMを操作するしかありません。

:emptyの代替として、空白を含む空要素に適応できる:-moz-only-whitespaceという疑似クラスが存在しますがFirefoxでしか適用されません。
W3CのSelectors Level 4では:empty:-moz-only-whitespaceと同等の動作をするように変更されたということですが、まだ対応するブラウザはありません。今後に期待です。

JavaScriptで空要素にクラスを付与、または要素を直接操作する

空白や改行がある空要素へのJavaScriptによる対処方法は、クラスを対象の要素に付与するか、直接要素を操作する方法になります。

クラスを付与する方法

クラスを付与して空要素を非表示にしたい場合、display:none;を設定したクラスをJavaScriptによって付与します。

上記のサンプルコードの場合は以下のような記述になります。

// 要素を非表示にするemptyというクラス
.flex div.empty {
  display: none;
}
const els = document.querySelectorAll(".flex > div");

els.forEach((el) => {
  if (el.innerHTML === null || !el.innerHTML.match(/\S/g)) {
    el.classList.add("empty");
  }
})

flexクラスが付与されているdivの子要素を一つずつ条件分岐にかけています。

上記の場合、子要素の中身が完全に空(=null)、もしくは空白以外の文字列を含まないときにemptyクラスを付与して非表示にしています。

直接要素を操作する場合

クラスを付与する方法と流れは同じですが、空白や改行のみ含む子要素だけを操作しています。

const els = document.querySelectorAll(".flex > div");

els.forEach((el) => {
  if (el.innerHTML === null || !el.innerHTML.match(/\S/g)) {
    el.remove(); // 条件に当てはまる子要素だけを削除
  }
})

最後に

いかがでしょうか?

:emptyは完全な空要素には有効ですが空白や改行が一つでも含まれると効かなくなってしまうのがネックです。

直接HTMLを操作できるなら:emptyを、そうでなければJavaScriptを使って非表示用クラスを付与したり直接操作したりするなど、管理しやすいやり方で使い分けていきましょう。

Live Serverを使ってPCブラウザだけじゃなくスマホ実機で簡単にライブプレビューする方法

WebサイトのコーディングでVScodeを使っている方、表示確認は何を使っていますか?

おそらくLive Serverを使っている方が多いんじゃないでしょうか。

ただ、Live Serverをインストールしただけの状態で使っているとPCでしか表示確認ができなくて、スマホでの表示はブラウザのデベロッパーツールでスマホモードを使うことでしか確認できません。

スマホでの表示はデベロッパーツールだけだと不十分で、実機を使って確認しないと思わぬ表示崩れが起きていることもしばしば。

だからといって、サーバーにアップロードしてスマホ実機で確認して、問題があったら修正してまたアップロードして・・・と繰り返すのは何とも手間ですよね。

今回は、Live Serverを使ったPCもスマホ(実機)も同時に確認できる方法のご紹介です。

まずはLive Serverをインストール

初めに、Live Serverをまだインストールしていない方は下のリンクからアクセスするか、VScodeの拡張機能検索で「Live Server」と検索してインストールしてください。

[

Live Server – Visual Studio Marketplace

Extension for Visual Studio Code – Launch a development local Server with live reload feature for static & dynamic pages

marketplace.visualstudio.com

](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer "Live Server – Visual Studio Marketplace")

スマホ実機で見るための設定

インストールができたら、設定の検索から「live server use local ip」と入力して、出てきた項目にチェックを入れてください。

設定はたったこれだけです。

設定が上手くいっているか確認

表示を確認したいページでLive Serverを使って表示します。

右下の「Go Live」をクリックするか、ショートカットキー「Alt+L→Alt+O」でライブプレビュー開始です。

スマホで表示

PCでプレビューしたページのURLをスマホのブラウザに入力して表示確認をします。

ただ、URLをスマホのブラウザで直接打ち込んだりするのは非常に面倒くさいので、ページのQRコードを表示してスマホで読み込んでしまいましょう。

PCでのブラウザはChromeを使います。表示確認自体はChrome以外でもいいのですが、スマホとページの共有するのが簡単なので今回はChromeで進めています。
Chrome以外でもQRコード出力機能があればお好みのブラウザでOKです。

Chromeのアドレスバー(URLが表示されるところ)の右側に共有ボタンがあります。

クリックすると「QRコードを作成」という項目があるので選択します。

するとQRコードが表示されるので、スマホのQRコードリーダーで読み込むだけでスマホ実機での表示確認できるようになります。

VScodeで変更を保存した瞬間にPCとスマホの両方で変更が反映されるのが素晴らしいところですね!

スマホ対応は当たり前の時代になっているので、スマホ表示確認でお困りの方はぜひこの機能使ってみてください。

CSSで色変更もできるSVGアイコンを使うための3ステップ

こんにちは。mimihokuro(みみほくろ)です。

みなさんはWebデザインでアイコンをつけたいとき、何を使いますか?

画像を読み込む、疑似要素を使って描画などがよくある方法かと思いますが、今回はSVGを使ったアイコン表示について紹介します。

SVGとは

SVGはWebに適したベクターファイル形式の画像フォーマットの一つで、拡大縮小してもPNG画像やGIF画像のように解像度を損なうことがないという大きなメリットを持ちます。

また、図形をテキストで情報を保持しているため、ファイルサイズが小さく、テキストとしてSEO的にも効果があることもメリットの一つです。

ただ、写真のような複雑な画像には適していないので、アイコンのようなシンプルな画像に使うことが主な使用用途になります。

SVGの中身を見ると、簡単な図形であっても一見複雑なためにかなり取っつきにくく感じると思います。が、基本的に内容を大きく変えることはないので、画像自体のサイズや色などの調整ができれば十分です。

調整なくそのままでも使えますが、最適化することでさらにファイルサイズの縮小ができSEOへの影響も期待できます。

SVGの構造

それでは基本的なSVGファイルのコードを見ていきましょう。

アイコンはGoogle Iconsから引用

<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M796-121 533-384q-30 26-69.959 40.5T378-329q-108.162 0-183.081-75Q120-479 120-585t75-181q75-75 181.5-75t181 75Q632-691 632-584.85 632-542 618-502q-14 40-42 75l264 262-44 44ZM377-389q81.25 0 138.125-57.5T572-585q0-81-56.875-138.5T377-781q-82.083 0-139.542 57.5Q180-666 180-585t57.458 138.5Q294.917-389 377-389Z"/></svg>

シンプルな形状のアイコンでもコード上で見るとなかなかに複雑ですね。

SVGアイコンに色情報を付与する

Google Iconsから取得したままの状態だと色情報を持っていないので、fill属性を使って色情報を与えます。

<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="#ff0000"><path d="M796-121 533-384q-30 26-69.959 40.5T378-329q-108.162 0-183.081-75Q120-479 120-585t75-181q75-75 181.5-75t181 75Q632-691 632-584.85 632-542 618-502q-14 40-42 75l264 262-44 44ZM377-389q81.25 0 138.125-57.5T572-585q0-81-56.875-138.5T377-781q-82.083 0-139.542 57.5Q180-666 180-585t57.458 138.5Q294.917-389 377-389Z"/></svg>

svgタグにfill属性を付与しました。この場合アイコンが赤色(#ff0000)になります。

これで色変更ができるSVGアイコンの基本形ができました。

SVGをCSSで色変更するための3ステップ

お待たせしました、ようやく本題です。

SVGはHTMLにインラインで記述もできますが、今回は疑似要素を使ってご紹介します。

.svg::before {
  content: "";
  display: block;
  width: 48px;
  height: 48px;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="%23ff0000"><path d="M796-121 533-384q-30 26-69.959 40.5T378-329q-108.162 0-183.081-75Q120-479 120-585t75-181q75-75 181.5-75t181 75Q632-691 632-584.85 632-542 618-502q-14 40-42 75l264 262-44 44ZM377-389q81.25 0 138.125-57.5T572-585q0-81-56.875-138.5T377-781q-82.083 0-139.542 57.5Q180-666 180-585t57.458 138.5Q294.917-389 377-389Z"/></svg>');
  background-size:100%;
  background-repeat: no-repeat;
}

一見SVGファイルのコードをそのまま貼り付けたように見えますが、3つポイントがあります。

  • data:image/svg+xml;utf8から始めよう
  • 包括するクォーテーションはシングル
  • 色コードの #%23 に変更する

data:image/svg+xml;utf8から始めよう

本来外部ファイルとして読み込むSVGファイルをインラインコードで埋め込むために必要なものです。今回のようなCSSでSVGを使う場合は必須です。

utf8は文字コードなので必要に応じて書き換えてください。

包括するクォーテーションはシングル

これはSVGファイルのコードにダブルクォーテーションが使われているので、その上からダブルクォーテーションで囲ってしまうとコードを分割したと判断されてしまうのでシングルクォーテーションで囲う必要があります。

mimihokuro

mimihokuro

ちなみにsvgタグ内のクォーテーションをすべてシングルにして、svgタグを囲うクォーテーションをダブルにしてもOKです。
でも、Google IconsでダウンロードしたものやPhotoshopなどで書き出したSVGファイルはsvgタグ内にダブルクォーテーションが使われているケースがほとんどなので、svgタグを囲うクォーテーションはシングルがおすすめです。

色コードの#を%23に変更する

かなり地味ですが、これが今回のキモです。

今回のようなアイコンを表示するためにbackground-imageでURLを指定してSVGファイルを読み込む場合、カラーコードを示す # は使えません。

そのため、URLエンコードを使って**#の代わりに%23に変換することで色コードを表現する**ことができます。

上記のコードでは「#ff0000」を「%23ff0000」に変換しています。

複数個所で使うならSCSS/SASSで共通化が便利!

ここからはSCSS/SASSを使った便利な方法のご紹介です。

複数個所で使う場合、すべてコピペするのはナンセンスですし、いざ変更が入ったときにすべて修正するのは大変です。

SCSS/SASSにはよく使うコードを共通化できるmixinという機能があって、使いたい箇所で呼び出すと定義してあったスタイル一式をCSSにコンパイルした時に出力してくれる便利な機能です。

mixinは引数も渡せるので、今回のような色だけ変更したいけど他は同じものを表示したいよ、というときにもよく使います。

コード

@mixin svgIcon($baseColor: "dddddd") {
  width:48px;
  height:48px;
  display: block;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="%23#{$baseColor}"><path d="M796-121 533-384q-30 26-69.959 40.5T378-329q-108.162 0-183.081-75Q120-479 120-585t75-181q75-75 181.5-75t181 75Q632-691 632-584.85 632-542 618-502q-14 40-42 75l264 262-44 44ZM377-389q81.25 0 138.125-57.5T572-585q0-81-56.875-138.5T377-781q-82.083 0-139.542 57.5Q180-666 180-585t57.458 138.5Q294.917-389 377-389Z"/></svg>');
  background-size:100%;
  background-repeat: no-repeat;
}

.svg {
  &::before {
    content: "";
    @include svgIcon($baseColor: "00ff00");
  }
}

@mixinでスタイルを一式定義(この場合svgIcon)して、@includeで定義したスタイルをカラーコード#00ff00(緑色)を引数として渡して呼び出します。

引数はsvgタグの色コードの部分に割り当ててあるので、この場合カラーコード#00ff00のSVGアイコンが表示されます。

さらにmixinは初期値も持たせることができるので、色の指定がなければ初期値の色で表示させることが可能です。この場合#ddddddを初期値として設定しています。

応用編

ここからはさらにテクニカルな方法をご紹介します。

文字列を一部だけ抽出するstr-slice関数

SCSS/SASSにはstr-sliceという指定の位置の文字列を抽出する便利な関数が存在します。

詳しい使い方はこちらの記事で紹介しています。

[

SASS/SCSSでJavaScriptのように文字列の一部を取り出す方法

こんにちは。みみほくろです。今回はJavaScriptでよく見る文字列の一部を取り出す方法をSCSS/SASSで行う方法をご紹介します。私はSCSSを採用しているため、サンプルコードはSCSSの記法になります。SASSを採用している方は変換…

mimihokuro.com

](https://mimihokuro.com/blog/extract-string-by-sass-scss/ "SASS/SCSSでJavaScriptのように文字列の一部を取り出す方法")

SCSS/SASSを使うとき、よく色コードを変数に格納して使うことが多いと思いますが、コンパイルすると「#」も含んでいるため上記でご紹介した方法でSVGが使えません。

そこで、str-sliceで変数から#を除いた色コードだけを抽出して、定義したmixinに渡すことで直接色コードを指定することなく使いまわせます。

str-slice関数を使ったコード

変数に色コードを格納し、mixinで使いまわせるように定義したコードがこちら!

$svg-color: #0000ff;

@mixin svgIcon($baseColor: "#dddddd") {
  display: block;
  width:48px;
  height:48px;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="%23#{str-slice(#{$baseColor}, -6)}"><path d="M796-121 533-384q-30 26-69.959 40.5T378-329q-108.162 0-183.081-75Q120-479 120-585t75-181q75-75 181.5-75t181 75Q632-691 632-584.85 632-542 618-502q-14 40-42 75l264 262-44 44ZM377-389q81.25 0 138.125-57.5T572-585q0-81-56.875-138.5T377-781q-82.083 0-139.542 57.5Q180-666 180-585t57.458 138.5Q294.917-389 377-389Z"/></svg>');
  background-size:100%;
  background-repeat: no-repeat;
}

.svg {
  &::before {
    content: "";
    @include svgIcon($baseColor: $svg-color);
  }
}

ちなみにこれをコンパイルするとこうなります。

.svg::before {
  content: "";
  width:48px;
  height:48px;
  display: block;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="%230000ff"><path d="M796-121 533-384q-30 26-69.959 40.5T378-329q-108.162 0-183.081-75Q120-479 120-585t75-181q75-75 181.5-75t181 75Q632-691 632-584.85 632-542 618-502q-14 40-42 75l264 262-44 44ZM377-389q81.25 0 138.125-57.5T572-585q0-81-56.875-138.5T377-781q-82.083 0-139.542 57.5Q180-666 180-585t57.458 138.5Q294.917-389 377-389Z"/></svg>');
  background-size:100%;
  background-repeat: no-repeat;
}

いかがでしたでしょうか?

SVG画像はほとんどのブラウザでサポートするようになりましたし、Google Iconsのような商用OKで無料提供しているサイトも多数あって、非常に便利になりました。

この記事を読んでSVGアイコン使ってみようと思っていただけると嬉しいです!