現場で使ってるCSS 20

DIST.38 「CSSな夜」

2022/12/09

自己紹介

株式会社ピクセルグリッド

げこたん(坂巻翔大郎)

プロパティ

  • 1.Custom Properties
  • 2.gap
  • 3.translate: X Y;
  • 4.scroll-behavior
  • 5.accent-color
  • 6.inset
  • 7.margin-block/inline

  • 8.width: max-content;
  • 9.currentColor
  • 10.display: contents;

セレクタ

  • 11.:is()
  • 12.:has()

小技

  • 13.border-radius: 9999px;
  • 14.visually hidden
  • 15.一部は幅いっぱい
  • 16.列幅揃える横並びのdt dd
  • 17.吹き出しの三角 (border)
  • 18.吹き出しの三角 (clip-path)
  • 19.visibility + opacity のフェードインアウト

気をつけた方がいいこと

  • 20.::backdrop はプロパティ継承しない

CSS プロパティ 編

1. Custom Properties

CSS プロパティ

ちょっと使うだけでも便利

div {
  --_size: 20px;
  width: var(--_size);
  height: var(--_size);
}

2. gap

CSS プロパティ

アイコンとテキスト横並び

<button class="IconWithText" type="button">
  <svg>...</svg>
  <span class="IconWithText_Text">テキスト</span>
</button>
.IconWithText {
  display: flex;
  align-items: center;
  gap: 10px;
}

Demo

ボタン横並び

<ul class="ButtonList">
  <li>
    <button class="IconWithText" type="button">...</button>
  </li>
  <li>
    <button class="IconWithText" type="button">...</button>
  </li>
  <li>
    <button class="IconWithText" type="button">...</button>
  </li>\u2028</ul>
.ButtonList {
  display: flex;
  gap: 10px;
}

Demo

3. translate: X Y Z;

CSS プロパティ

プロパティでもかけるようになりました。

div {
  transform: translate(10px, 20px);
}

div {
  translate: 10px 20px;
}
  • MDN
  • rotate ある
  • scale ある
  • skew ない

4. scroll-behavior

CSS プロパティ

なめらかにスクロールさせるやつ

:root {
  scroll-behavior: smooth;
}
.scroll-container {
  overflow-y: scroll;
  scroll-behavior: smooth;
}

scroll-behavior は CSS のプロパティで、ナビゲーションや CSSOM のスクローリング API によってスクロールするボックスにスクロールが発生した際の、そのスクロールの振る舞いを設定します。

MDN

5. accent-color

CSS プロパティ

accent-color

accent-color は CSS のプロパティで、一部の要素で生成されるユーザーインターフェイス要素の強調表示色を設定します。

MDN

チェックボックスなどの色を変える

<input type="checkbox">
<input type="checkbox" checked>
<input type="radio">
<input type="radio" checked>
<input type="range">
<progress></progress>
input {
  accent-color: red;
}

macOS Chrome 107

macOS Firefox 107

macOS Safari 15.5

6. inset

CSS プロパティ

inset

inset は CSS のプロパティで、 top, right, bottom, left に対応する一括指定です。これは margin の一括指定における複数値の場合と同じ構文です。

MDN

top / right / bottom / left をまとめて指定できる

div {
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

div {
  inset: 0;
}

7. margin-block/inline

CSS プロパティ

margin-block

margin-block は CSS の一括指定プロパティで、論理的なブロックの先頭と末尾のマージンを設定します。これは要素の書字方向やテキストの向きに応じて物理的なマージンに変換されます。

MDN

margin-inline

The margin-inline は CSS の一括指定プロパティで、論理的なインライン方向の先頭と末尾のマージンを設定します。これは要素の書字方向やテキストの向きに応じて物理的なマージンに変換されます。

MDN

中央寄せといえば…

div {
  margin: 0 auto;
} 
/* OR */
div { 
  margin-right: auto;
  margin-left: auto;
}

margin-inlineを使うと、

margin-leftとmargin-rightを一括指定できる*1

div {
  margin-inline: auto;
}
  • *1 厳密には margin-inline-start と margin-inline-end を一括指定できる

CSS 値 編

8. width: max-content;

CSS 値

max-contentとは

max-content は大きさのキーワードで、コンテンツの内在的な最大幅や高さを表しています。テキストコンテンツの場合は、オーバーフローが発生しても、コンテンツはまったく折り返されないことを意味します。

MDN

max-content / min-content / fit-content

<div class="Wrap">
  <p class="MaxContent">これはtextです。</p>
  <p class="MinContent">これはtextです。</p>
  <p class="FitContent">これはtextです。</p>
</div>
.Wrap {
  width: 100px;
  outline: 3px dotted red;
}
.MaxContent {
  width: max-content;
  background-color: tomato;
}
.MinContent {
  width: min-content;
  background-color: salmon;
}
.FitContent {
  width: fit-content;
  background-color: lime;
}

Demo

9. currentColor

CSS 値

currentColor

currentColor キーワードは、要素の color プロパティの値を表します。これで color の値をプロパティが既定で受け取らなくても利用することができます。

MDN

currentColorを使う

<!-- box-shadowの色は初期値がcurrentColor -->
<p style="color: tomato; box-shadow: 0 0 10px;">
  テキストが入ります。
</p>
<!-- borderの色は初期値がcurrentColor --> 
<p style="color: tomato; border: 1px solid;">
  テキストが入ります。
</p>
 
<p style="color: tomato;">
  <svg width="12" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="略" fill="currentColor"/></svg>
  テキストが入ります。
</p>

currentColorはSVG由来

Demo

10. display: contents;

CSS 値

display: contents;

これらの要素は自身のために特定のボックスを生成しません。擬似ボックスやその子ボックスで置き換えられます。

fieldset要素に使う

<fieldset>
  <legend>好きな果物をひとつ選ぶ</legend>
  <label><input type="radio" name="fruits">りんご</label>
  <label><input type="radio" name="fruits">みかん</label>
</fieldset>  
<hr>
  
<fieldset style="display: contents;">
  <legend>好きな果物をひとつ選ぶ</legend>
  <label><input type="radio" name="fruits">りんご</label>
  <label><input type="radio" name="fruits">みかん</label>
</fieldset>

Demo

astroで使ってる

astroではastro-islandastro-slotという 独自の要素に対してdisplay: contents;を適用している。

注意点

大部分のブラウザーの現在の実装では、アクセシビリティツリーから display の値が contents であるすべての要素を削除します (ただし子孫は残ります)。これにより、その要素自身は読み上げソフトでは読み上げられなくなります。これは CSS 仕様書によれば正しくありません。

MDN

プロパティ

  • 1.Custom Properties
  • 2.gap
  • 3.translate: X Y;
  • 4.scroll-behavior
  • 5.accent-color
  • 6.inset
  • 7.margin-block/inline

  • 8.width: max-content;
  • 9.currentColor
  • 10.display: contents;

セレクタ

  • 11.:is()
  • 12.:has()

小技

  • 13.border-radius: 9999px;
  • 14.visually hidden
  • 15.一部は幅いっぱい
  • 16.列幅揃える横並びのdt dd
  • 17.吹き出しの三角 (border)
  • 18.吹き出しの三角 (clip-path)
  • 19.visibility + opacity のフェードインアウト

気をつけた方がいいこと

  • 20.::backdrop はプロパティ継承しない

CSS セレクタ 編

11. :is()

CSS セレクタ

:is()

:is() は CSS の擬似クラス関数で、セレクターのリストを引数に取り、リスト中のセレクターの何れか一つに当てはまる要素をすべて選択します。数多くのセレクターを小さくまとめて書くのに便利です。

MDN

:is()を使うとセレクタが短くかけることがある

table th,
table td {
  padding: 10px;
}
table :is(th, td) {
  padding: 10px;
}

12. :has()

CSS セレクタ

:has()

:has() は CSS の擬似クラスで、引数として渡されたセレクターに (指定された要素の :scope の相対で) 該当する要素が一つ以上の要素に一致することを表します。

:has() 擬似クラスは、セレクターの相対的なリストを引数に取ります。

MDN

Firefoxではまだ使えません(執筆現在v107)

〜を持つ要素にマッチする

table:not(:has(tbody)) {
  color: gray;
  border-color: gray;
}
<table>
  <thead>
    <tr><th>見出し</th><th>見出し</th><th>見出し</th></tr>
  </thead>
  <tbody>
    <tr><td></td><td></td><td></td></tr>
  </tbody>
</table>
 
<table>
  <thead>
    <tr><th>見出し</th><th>見出し</th><th>見出し</th></tr>
  </thead>
</table>

Demo

CSS 小技 編

13. border-radius: 9999px;

CSS 小技

%以外の大きい値を指定すればよし

<div>
  テキストが入ります。<br/>テキストが入ります。
</div>
div {
  padding: 10px 20px;
  background: tomato;
  border-radius: 9999px;
}

Demo

14. Visually Hidden

CSS 小技

見た目だけ隠す

.VisuallyHidden {
 position: absolute;
 clip: rect(1px, 1px, 1px, 1px);
 padding: 0;
 border: 0;
 height: 1px;
 width: 1px;
 overflow: hidden;
}
  • 画面上は見えなくても支援技術(スクリーンリーダーなど)は認識する
  • フォーカスできる
  • Bootstrap v5.0 にもある
  • Tailwindではsr-only
  • SEO(?)のために使わない使えない

カスタムチェックボックスやラジオボタンを作るとき

<label class="Checkbox">
  <input type="checkbox" class="VisuallyHidden" />
  <span class="Checkbox_Icon"></span>
  <span class="Checkbox_Text">同意する</span>
</label>
  • input要素にdisplay: none;は使わない。使うとフォーカスできない。
  • input要素を隠しつつフォーカスできるようにVisually Hiddenを使う

ハイコンテキストなテキストを補完したいとき

<p>
  ...
  <a href="/news/2022-12-7">
    <span class="VisuallyHidden">2022年12月7日の記事を</span>もっと見る
  </a>
</p>
<p>
  ...
  <a href="/news/2022-12-8">
    <span class="VisuallyHidden">2022年12月8日の記事を</span>もっと見る
  </a>
</p>
  • スクリーンリーダーには、ページ中のリンクを一覧表示する機能があるが、「もっと見る」がいっぱいあるとユーザーは正しく判断できない
  • そもそも隠さずリンク先の内容を推測しやすいリンクテキストに見直すほうが良い

15. 一部は幅いっぱい

CSS 小技

CSS Gridを使用する

<div class="Box">
  <div class="Box_Item">テキストが...</div>
  <div class="Box_Item -full">テキストが...</div>
  <!-- 略... -->
</div>
.Box {
  display: grid;
  grid-template-columns:
    [full-start]
      minmax(20px, 1fr)
      [main-start]
        minmax(0, 500px)
      [main-end]
      minmax(20px, 1fr)
    [full-end];
  row-gap: 10px;
}
.Box > *  {
  grid-column: main;
}
.Box_Item.-full {
  grid-column: full;
}

CSS Gridを使用する

<div class="Box">
  <div class="Box_Item">テキストが...</div>
  <div class="Box_Item -full">テキストが...</div>
  <!-- 略... -->
</div>
.Box {
  display: grid;
  grid-template-columns:
    [full-start]
      minmax(20px, 1fr)
      [main-start]
        minmax(0, 500px)
      [main-end]
      minmax(20px, 1fr)
    [full-end];
  row-gap: 10px;
}
.Box > *  {
  grid-column: main;
}
.Box_Item.-full {
  grid-column: full;
}

画面幅が広い時

画面幅が狭い時

Demo

16. 列幅揃える横並びのdt dd

CSS 小技

1列目の幅は一番長いものに揃えたい

<dl>
  <dt>げこたん</dt>
  <dd>さかまきしょうたろうさんの<br>ニックネーム。</dd>
  <dt>ピクセルグリッド</dt>
  <dd>げこたんが勤めている会社の名前</dd>
</dl>
dl {
  display: grid;
  grid-template-columns:
    [key] max-content
    [value] 1fr
  ;
  margin: 0;
  gap: 10px;
}
dt {
  grid-column: key;
  background-color: tomato;
}
dd {
  grid-column: value;
  margin: 0;
  background-color: limegreen;
}

Demo

実例

CodeGridのお問合せフォーム

17. 吹き出し用の三角形 (border)

CSS 小技

borderで三角形を作る

<div class="triangle  -top"></div>
<div class="triangle  -right"></div>
<div class="triangle  -bottom"></div>
<div class="triangle  -left"></div>
.triangle {
  --_bg: red;
  --_size: 50px;
  --_size-side: calc(var(--_size) / 2);
  --_size-bottom: var(--_size);
  display: inline-block;
  width: 0;
  height: 0;
  border-style: solid;
  border-color: transparent;
}
.triangle.-top {
  border-width: 0 var(--_size-side) var(--_size-bottom) var(--_size-side);
  border-bottom-color: var(--_bg);
}
.triangle.-right {
  border-width: var(--_size-side) 0 var(--_size-side) var(--_size-bottom);
  border-left-color: var(--_bg);
}
.triangle.-bottom {
  border-width: var(--_size-bottom) var(--_size-side) 0 var(--_size-side);
  border-top-color: var(--_bg);
}
.triangle.-left {
  border-width: var(--_size-side) var(--_size-bottom) var(--_size-side) 0;
  border-right-color: var(--_bg);
}

Demo

18. 吹き出しの三角 (clip-path)

CSS 小技

パスを引いて三角形を作る

<div class="triangle  -top"></div>
<div class="triangle  -right"></div>
<div class="triangle  -bottom"></div>
<div class="triangle  -left"></div>
.triangle {
  --_bg: red;
  --_dir-top: polygon(50% 0%, 0% 100%, 100% 100%);
  --_dir-right: polygon(0% 0%, 100% 50%, 0% 100%);
  --_dir-bottom: polygon(0% 0%, 100% 0%, 50% 100%);
  --_dir-left: polygon(100% 0%, 100% 100%, 0% 50%);
  --_size: 50px;
  
  display: inline-block;
  width: var(--_size);
  height: var(--_size);
  clip-path: var(--_dir);
  background-color: var(--_bg);
}

.triangle.-top { --_dir: var(--_dir-top); }
.triangle.-right { --_dir: var(--_dir-right); }
.triangle.-bottom { --_dir: var(--_dir-bottom); }
.triangle.-left { --_dir: var(--_dir-left); }

Demo

19. visibility + opacityのフェードインアウト

CSS 小技

開閉するメニュー

<button title="メニュー">🍔</button>
<div class="Menu">
  メニューです
</div>
.Menu {
  visibility: hidden;
  opacity: 0;
  transition-duration: 0.1s;
  transition-timing-function: linear;
  transition-property: visibility, opacity;
}
/* JSで付与 */
.Menu.-expanded {
  visibility: visible;
  opacity: 1;
  transition-duration: 0.3s;
}

Demo

visibility は CSS のプロパティで、文書のレイアウトを変更することなく要素を表示したり非表示にしたりします。

要素の visibility の値に hidden を使用すると、 アクセシビリティツリーから削除されます。これは要素及びその子孫要素が読み上げ技術でアナウンスされない結果になります。

visibility の値は可視及び不可視の間で補間可能です。 従って、開始または終了の値の一つが visible でない限りは、補間は行われません。値は離散的なステップとして補間され、タイミング関数の 0 と 1 間の値が、 visible に対応し、タイミング関数の他の値 (トランジションの開始点または終了点でのみ、または [0、1] の外側の y 値を有する cubic-bezier() 関数の結果として) はより近い終了点に対応します。

CSS 気をつけた方がいいこと 編

20 ::backdrop はプロパティ継承しない

CSS 気をつけた方がいいこと

やりたくてもできなかったこと

:root {
  --bg: red;
}
 
::backdrop {
  /* :rootから--bgを継承しないので無効 */
  background-color: var(--bg);
}
  • ::backdrop擬似要素では祖先要素で定義したカスタムプロパティが使えない

    ::backdrop 擬似要素はどの要素にも継承せず、どの要素からも継承しません。この擬似要素に適用するプロパティの制限はありません。

MDN

プロパティ

  • 1.Custom Properties
  • 2.gap
  • 3.translate: X Y;
  • 4.scroll-behavior
  • 5.accent-color
  • 6.inset
  • 7.margin-block/inline

  • 8.width: max-content;
  • 9.currentColor
  • 10.display: contents;

セレクタ

  • 11.:is()
  • 12.:has()

小技

  • 13.border-radius: 9999px;
  • 14.visually hidden
  • 15.一部は幅いっぱい
  • 16.列幅揃える横並びのdt dd
  • 17.吹き出しの三角 (border)
  • 18.吹き出しの三角 (clip-path)
  • 19.visibility + opacity のフェードインアウト

気をつけた方がいいこと

  • 20.::backdrop はプロパティ継承しない

フロントエンドに関わる人々のためのオンラインメディア

このような話をCodeGridというメディアで書いてるのでよかったら講読してください。(私の記事は193記事)

おわり

質問などあればお気軽にお声がけください。