About Blog Contact

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

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;を使うことで英単語の途中でも改行してくれるので、長い単語でもはみ出さずに改行させることができます。

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

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を使って非表示用クラスを付与したり直接操作したりするなど、管理しやすいやり方で使い分けていきましょう。

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アイコン使ってみようと思っていただけると嬉しいです!

text-align: justifyでテキストを両端揃えにしたら文字間が開きすぎた・・・。word-break:break-allで解決!

サイト構築する上で長文のテキストを表示することはよくあると思います。

でも左右に寄せたテキストを改行したとき、端に余分なスペースができて見た目が悪いな、ってことありませんか?

そんなときに役立つのがtext-align: justify;

text-align は CSS のプロパティで、ブロック要素または表のセルボックス内におけるインラインレベルコンテンツの水平方向の配置を設定します。つまり、 vertical-align と同じように機能しますが、水平方向に機能します。

text-align – CSS | MDN

text-align は CSS のプロパティで、ブロック要素または表のセルボックス内におけるインラインレベルコンテンツの水平方向の配置を設定します。つまり、 vertical-align と同じように機能しますが、水平方向に機能します。

改行によってできた行末の余白を文字間に自動で割り振って両端を揃えてくれる便利なCSSスタイルですが、実は問題があります。

それが文字間が開きすぎてしまう問題です。

文字間が開きすぎるってどういうこと?

どういうことなのか、画像をご覧ください。

左がスタイルなしテキスト。右がtext-align; justifyを指定したテキスト。

何もスタイルを指定していないテキストに比べて、text-align: justify;を指定しているテキストは両端が揃っている部分は見た目にはいい感じですが、一部文字間が開きすぎてしまっています。

これは日本語文と半角英数字を組み合わせたときに起きやすく、特に英単語は途中で改行されないので、次の行に移った英単語があったスペース分だけ空いてしまいます。text-align: justify;はその空いたスペースを文字間に割り振ってしまうため間延びした状態にしてしまうのです。

この問題を解決するのがword-break: break-all;です。

word-break: break-all;のメリット

word-break: break-all;を指定することで何が起きるのか?ということですが、下の画像をご覧ください。

左はtext-align: justifyのみ。右はtext-align: justifywork-break: break-all

text-align: justify;だけ指定したテキストで改行されなかった英単語が途中で改行されています。

そうです!word-break: break-all;text-align: justify;を組み合わせることで、両端を揃えつつ、英単語が行末に位置しても途中で改行されて文字間が必要以上に空くことがありません。

word-break: break-all;のデメリット

もちろんいいことだけではありません。

両端揃えにしたときに必要以上に文字間が空いてしまう問題は解決できますが、英単語が途中で改行されてしまうことは可読性を下げてしまうというデメリットが出てきてしまいます。

ですが、一部だけ文字間の空いた日本語文というのは、日常では見慣れないし読みづらいと思います。

最後に

必要以上に空いた文字間と途中で改行される英単語では、後者の方がユーザーにとっては読みやすいものではないかと感じます。(個人の見解です)

状況によって使い分ける、もしくはテキスト構成の見直しなどして上手く付き合っていくことが大事になります。

Posted in CSS

Tailwind CSSを導入したいけどスタイルが反映されない?Unknown at rule @tailwind エラーを解消する3つの方法

クラス名を考える必要がなかったり、HTMLとCSSを行き来しながらコーディングする必要がないなど、モダンなフロントエンドで人気のあるTailwind CSSですが、導入時に躓きやすいのが難点です。

公式サイトの「Get started」ページの通りに進めてみたけど、指定したスタイルが反映されなかったりエラーになる・・・といったことも。

エラーが発生しやすい箇所がこちらです。

@tailwind base;
@tailwind components;
@tailwind utilities;

Tailwind CSSを有効化するための構文ですが、「Unknown at rule @tailwind」とエラーメッセージが表示される場合は、構文が正しく認識されていないため別で拡張機能や設定が必要になります。

※この記事はエディターにVScodeを使っている前提となっています。

エラー解消に必要な拡張機能のインストール

エラーを解消するには二つの拡張機能をインストールする必要があります。

それが「T****ailwind CSS IntelliSense」と「PostCSS Language Support」です。

Tailwind CSSインストール手順の中で「tailwindcss」と「postcss」の二つのパッケージをnpm経由でインストールしますが、その二つをVScodeで有効化するための拡張機能です。

[

Tailwind CSS IntelliSense – Visual Studio Marketplace

Extension for Visual Studio Code – Intelligent Tailwind CSS tooling for VS Code

marketplace.visualstudio.com

](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss "Tailwind CSS IntelliSense – Visual Studio Marketplace")

[

PostCSS Language Support – Visual Studio Marketplace

Extension for Visual Studio Code – Syntax highlighting for modern and experimental CSS in VSCode

marketplace.visualstudio.com

](https://marketplace.visualstudio.com/items?itemName=csstools.postcss "PostCSS Language Support – Visual Studio Marketplace")

言語モードの変更による適応

上記の拡張機能をインストールしてもエラーが解消されない場合は、言語モードを設定してTailwind CSSに対応させましょう。

手順はこちらです。

  1. Tailwind CSSサポート構文(global.css)を記述したCSSファイルを開く
    • 先ほどご紹介したTailwind CSSサポート構文(@tailwind base;とか)を記述したCSSファイル(global.css)を開いて以下の方法を行います。
  2. コマンドパレットを開いて言語モードを変更する
    • 「Shift+Ctrl+P」でコマンドパレットを開き、「change language mode」と入力します。
    • プレースホルダーに「言語の選択」とあるので「tailwind」と入力し、候補に出てきた「Tailwind CSS」を選択します。

Tailwind CSS IntelliSenseをインストールしていないと候補に出てこないので拡張機能のインストールを先に行いましょう。

@ルールを無視する

言語モードの変更のほかに、@ルール(Tailwind CSSサポート構文)自体を無視する方法もあります。

VScodeのsetting.jsonに次のコードを追加します。

"css.lint.unknownAtRules": "ignore"

SCSSを使っている場合は次のコードを使ってください。

"scss.lint.unknownAtRules": "ignore"

また、@ルールを無視するには設定画面からも可能です

  1. 設定画面を開き「unknown at rules」と検索する
  2. 「CSS > Lint: Unknown At Rules」項目のプルダウンを「ignore」に変更する

言語モードを変更するかignore設定のどちらかを行うことでエラーが解消されると思います。

最後に

ここまでお疲れ様でした。

表題のエラーは初めてTailwind CSSを触る人には躓きやすいポイントかと思います。

この記事がエラー解決の助けになれば幸いです。

それでは快適なTailwind CSSライフをお送りください!

【2026年最新】モーダルウィンドウ実装の最適解!脱z-indexなモダン手法をまるっと解説

ユーザーに重要な確認を求めたり、画面遷移なしでサクッと情報を表示したり……。UIデザインにおいて「モーダルウィンドウ」はとっても便利で、Web開発でも欠かせない存在ですよね。

でも、いざ新しく実装しようと思ったとき、ふとこんな風に迷うことはありませんか?

「あれ? モーダルってどうやって実装するのが最新の正解なんだっけ?」

少し前までは <div> を重ねて、複雑なJavaScriptを書いて、z-index: 9999 を指定するような「自前実装」が当たり前でした。

しかし今は、ブラウザの標準APIが劇的に進化し、「脱z-index」で、より簡単かつ安全に実装できるアプローチが揃っています。

この記事では、「今、モーダルを実装するならどんな選択肢があるの?」という疑問にお答えすべく、2026年現在のモダンな実装手法をまるっと整理してご紹介します!

プロジェクトにぴったりの方法を一緒に見つけていきましょう。

2026年の「大本命」: <dialog>要素 + showModal()

2026年現在、モーダルウィンドウを実装するなら真っ先に選びたいのが、HTMLのネイティブ要素である <dialog> です。

JavaScriptの .showModal() メソッドと組み合わせるだけで、びっくりするくらい簡単に、しかもアクセシビリティに優れたモーダルが作れちゃいます。

なぜこれが大本命なの?

自分で一から作るのとは違い、ブラウザが以下のような「欲しかった機能」を標準で提供してくれるからです。

  • Top Layerに確実に出る: もう z-index の数値の戦いとは無縁です! DOMツリーのどこに書いても、確実に最前面(Top Layer)に表示されます。
  • 自動フォーカストラップ: モーダルが開いている間、Tabキーでの移動がモーダルの中に自動で閉じ込められます。
  • 背面コンテンツのブロック (inert): モーダルが開いている間は、後ろのボタンが押せなくなったり、スクリーンリーダーの読み上げが防がれたりする処理を勝手にやってくれます。
  • Escキーでサクッと閉じる: ユーザーにとって嬉しい基本機能がデフォルトで備わっています。

実際の実装コード

<dialog id="my-modal">
  <div class="dialog-window">
    <p>Hello,Dialog!</p>
    <button id="close-btn">CLOSE</button>
  </div>
</dialog>

<button id="open-btn">OPEN</button>
const modal = document.getElementById('my-modal');
const openBtn = document.getElementById('open-btn');
const closeBtn = document.getElementById('close-btn');

// モーダルを開く
openBtn.addEventListener('click', () => modal.showModal());

// モーダルを閉じる
closeBtn.addEventListener('click', () => modal.close());

背景の暗転(オーバーレイ)も、CSSの ::backdrop 擬似要素を使えば簡単にスタイリングできちゃいます。

dialog::backdrop {
  background-color: rgba(0,0,0,0.2);
  backdrop-filter: blur(4px); /* 背景を少しぼかすと、一気にリッチな印象に! */
}

See the Pen Modal (Vanilla-JS) by mimihokuro (@mimi_hokuro) on CodePen.

なんとJSすら不要に!? 最新仕様「Invoker Commands API」

「もっと手軽に使いたい!」「いちいちJSのイベントリスナーを書くのが面倒…」という方。最新トレンドの Invoker Commands API はぜひ知っておいてほしい仕様です。(2025年〜2026年にかけて主要ブラウザでサポートが整いました!)

なんと、HTMLに commandforcommand という属性を追加するだけで、ボタンとモーダルの連動が完結してしまうんです。

<!-- ボタンと対象のダイアログを属性だけで紐付け! -->
<button commandfor="invoker-modal" command="show-modal" class="open-btn">OPEN</button>

<dialog id="invoker-modal" class="dialog-window">
  <p>JavaScriptを1行も書かずに呼び出せたモーダルです。</p>
  
  <!-- 閉じるボタンも同じように属性だけでOK -->
  <button commandfor="invoker-modal" command="close" class="close-btn">CLOSE</button>
</dialog>

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

JavaScriptのフレームワークを使わない静的なページや、ちょっとしたお知らせ表示を作るときに、圧倒的なスピードで実装できちゃいますね。

アニメーションをCSSだけで滑らかに: @starting-style

<dialog> 要素は便利ですが、「フワッと出して、フワッと消すアニメーションがやりにくい」というのが、少し前までのフロントエンド界隈の大きな悩みでした。(display: none からのアニメーションが難しかったためです)

実はそれ、2026年現在ではCSS単体でとってもキレイに解決できるんです。新機能の @starting-styleallow-discrete を組み合わせるのが今のトレンドです。

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

これで、重たいアニメーションライブラリ(Framer Motionなど)や複雑なJSの実装に頼らなくても、美しくて滑らかな開閉アニメーションが実現できます!

便利な「Popover API」とはどう使い分ける?

同じように画面の最前面(Top Layer)を使う新しいAPIとして、popover 属性も話題ですよね。「全部 Popover でいいのでは?」と思うかもしれませんが、実は <dialog> とは得意なシーンが違います。

  • <dialog showModal()> を使うシーン: 画面全体をロックして、ユーザーに必ず応答してほしいとき。(重大な警告、フォームの入力、利用規約の同意など)
  • popover を使うシーン: 背景の操作を邪魔せず、外側をポチッとクリックしたらフワッと消えてほしいような、一時的な情報表示。(ドロップダウンメニュー、ツールチップ、ちょっとした通知など)

「今のユーザーの作業をストップさせるべきかどうか?」を基準にして、便利な機能を使い分けてみてくださいね。

ReactやVueでの開発なら:ヘッドレスUIという選択肢

「Web標準が便利なのは分かったけど、ReactやVueみたいなフレームワークで大規模なアプリを作るときはどうするの?」という疑問もあると思います。

複雑な状態(State)管理が必要な場合は、無理に自前で作るのではなく、アクセシビリティがしっかり担保されたヘッドレスUIライブラリ(Radix UI、React Aria、Ark UI、Headless UI など)の Dialog コンポーネントを使うのが、2026年現在も安心で便利な選択肢です。

これらのライブラリは、内部的に最新のWeb標準を上手に使いつつ、フレームワークにぴったりの使いやすい書き方(宣言的UI)を提供してくれます。

まとめ:用途に合わせて最適なモーダル実装を選ぼう!

便利なモーダルウィンドウを実装するための、2026年現在の選択肢をおさらいしましょう。

  1. 基本は迷わず <dialog>.showModal()
  2. JSを減らして手軽に作りたいときは Invoker Commands API を活用。
  3. アニメーションは @starting-style + CSSトランジションで完結。
  4. 用途によっては Popover API と使い分ける。
  5. 大規模なフレームワーク開発ならヘッドレスUIを活用する。

便利なモーダルだからこそ、ユーザーにとっても開発者にとっても優しい「今の正解」を選んでいきたいですよね。

ぜひこの記事を参考に、古い z-index 実装から卒業して、最新のWeb標準の進化を取り入れた快適なモーダル実装を試してみてください!

いかがでしょうか?今モーダルを実装したい環境にどんな方法を取るのがいいのか、悩まれていたのなら参考になれば幸いです。