💬

No.9 2021年4月にツイートしたHTML/CSS/JavaScriptのTipsまとめ

2021/12/13に公開約11,400字

2021 年 4 月にツイートした HTML/CSS/JavaScript のツイートまとめです。見出しをクリックするとツイート元に遷移するので、気に入ったらフォロー・ファボ・リツイートお願いします。

1. SVGとCSSでファビコン

<foreignObject> 要素を使えば CSS で上下中央揃えなどのスタイリングができます。

<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'><foreignObject width='100%' height='100%'><div xmlns='http://www.w3.org/1999/xhtml'><style>.canvas{display:grid;place-items:center;margin:0;width:100px;height:100px}.circle{width:60%;height:60%;border-radius:50%;background:red}</style><div class='canvas'><div class='circle'/></div></div></foreignObject></svg>">

2. :is()セレクタの便利な使い道

input[type="range"] 要素のつまみ部分を指定するときに、

::-webkit-slider-thumb, ::-moz-range-thumb { ... }

このように書いてしまうとブラウザが ::-webkit-slider-thumb に対応していない場合、あとの ::-moz-range-thumb は無視されてしまうため、Firefox でスタイルが適用されなくなってしまいます。

::-webkit-slider-thumb { ... }
::-moz-range-thumb { ... }

そのため、通常はこのように分けて書く必要があります。

:is(::-webkit-slider-thumb, ::-moz-range-thumb) { ... }

:is() セレクタを使えばまとめて記述できるようになります。

3. CSS Logical Properties のショートハンド

CSS Logical Properties は LTR / RTL(右から左に書く言語)両方に対応するときに便利なプロパティです。それに加え、既存のいくつかのプロパティをまとめて宣言できるショートハンドプロパティも追加されています。

inset プロパティ

inset プロパティは、top right bottom left プロパティのショートハンドです。

Before
.selector {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
After
.selector {
  position: absolute;
  inset: 0;
}

margin-inline プロパティ

margin-inline プロパティは、margin-left margin-right プロパティのショートハンドです。

Before
.selector {
  margin-left: auto;
  margin-right: auto;
}
.selector {
  margin-inline: auto;
}

4. CSS変数に関するクイズ

p 要素の背景色は何色になるでしょうか?

<html>
  <body>
    <article>
      <p>...</p>
    </article>
  </body>
</html>
html {
  --bg-color: var(--default-color, blue);
}
article {
  --default-color: red;
}
p {
  background-color: var(--bg-color);
}

Twitter でアンケートしてみたところ、 綺麗に redblue に割れました。答えは blue です。

--bg-color が定義された時点で、--default-color は定義されていないため、フォールバック値の blue が採用されます。CSS 変数は値が継承される前に解決されるので注意が必要です。

https://twitter.com/takamosoo/status/1380044593480134662

5. 半透明な線の縁取り

background-origin プロパティに border-box を指定すると背景画像の上に線を重ねることができます。擬似要素も必要ないため、シンプルに実装できます。

<div class="box"></div>
.box {
  width: 250px;
  height: 250px;
  border: 25px solid rgba(255, 255, 255, .25);
  background: linear-gradient(-45deg, #3fc1c9 50%, #364f6b 0);
  background-origin: border-box;
}

6. 文字列の切り出し

substr(start[, length])

start に負の値を指定すると後ろからになります。

const string = 'abcdefg'

string.substr(2, 4)  // cdef
string.substr(2)     // cdefg
string.substr(-2)    // fg

このメソッドは非推奨のようです。

https://twitter.com/petamoriken/status/1383088370398601216

substring(indexStart[, indexEnd])

substr() のように引数に負の値は使えません。

const string = 'abcdefg'

string.substring(2, 4)  // cd
string.substring(4, 2)  // cd
string.substring(2)     // cdefg

また、第 1 引数と第 2 引数を入れ替えても結果は変わりません。

slice(beginIndex[, endIndex])

第 1 引数と第 2 引数に負の値を使えます。

const string = 'abcdefg'

string.slice(2, 4)    // cd
string.slice(4, 2)    // 空文字
string.slice(2)       // cdefg
string.slice(-2)      // fg
string.slice(-4, -2)  // de

Array.from()

家族の絵文字のような合字は Array.from() でもうまくいかないため、graphemesplit のようなライブラリを使う必要があります。

const string = 'abcdefg'

Array.from('😍👏👏').slice(1, 2)  // 👏
Array.from('😍👨‍👩‍👦‍👦👏').slice(1, 2)  // 👨

7. 絵文字とUnicode

コード値の取得

charCodeAt() は UTF-16 コードユニットを返し、複数になる場合があります。codePointAt() は Unicode コードポイントを返します。

'😅'.split('').map(char => char.charCodeAt())  // [55357, 56837]
'😅'.split('').map(char => char.charCodeAt().toString(16))  // ['d83d', 'de05']
'😅'.codePointAt()  // 128517
'😅'.codePointAt().toString(16)  // 1f605

絵文字の取得

逆にコード値から文字に変換するには fromCharCode() または fromCodePoint() を使います。

String.fromCharCode(55357, 56837)    // 😅
String.fromCharCode(0xd83d, 0xde05)  // 😅
String.fromCodePoint(128517)         // 😅
String.fromCodePoint(0x1f605)        // 😅

エスケープシーケンス記法

4 桁の場合は \uXXXX のように記述しますが、5 桁になる場合は \u{XXXXX} という記法を使います。ちなみに正規表現でエスケープシーケンスを使う場合は u フラグをつけます。

'\ud83d\ude05' === '😅'     // true
'\u{d83d}\u{de05}' === '😅' // true
'\u{1f605}' === '😅'        // true
/\u{1f605}/u.test('😅')     // true

8. 多重ループとラベルの使い道

break ラベル

breakfor 文の前に記述できるラベルを使えば多重ループを抜けられます。

// 対象の配列
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
// テストする項目
const tests = [
  n => n >= 0,
  Number.isInteger,
  n => n < 6,
]
// 結果
let result = true

LOOP: for (const number of numbers) {
  for (const test of tests) {
    // 6未満でない数字があるため、このテストは6に達した時点で終了する
    if (!test(number)) {
      result = false
      // 多重ループを抜ける
      break LOOP
    }
  }
}

console.log(result)  // false

continue ラベル

continue ラベルを使うと、複数のテスト項目のうち 1 つでも失敗したらすぐ次の数字のテストにスキップできます。

// 対象の配列
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
// テストする項目
const tests = [
  n => n % 2 === 0,  // 2の倍数である
  n => n % 3 !== 0,  // 3の倍数でない
]
// 結果
const result = []

LOOP: for (const number of numbers) {
  for (const test of tests) {
    if (!test(number)) {
      // 外側のループにスキップする
      continue LOOP
    }
  }

  result.push(number)
}

console.log(result)  // [2, 4, 8]

9. 文字列のソート

String#localeCompare()

localeCompare() を使えば簡単に文字列を五十音順にソートできます。漢字のように色々な読み方がある文字はふりがなでソートするとよいです。

const names = ['Éthan', 'Oliver', 'Elijah', 'みなと', 'はるき', 'いつき']

names.sort((a, b) => a.localeCompare(b))

console.log(names)  // ['Elijah', 'Éthan', 'Oliver', 'いつき', 'はるき', 'みなと']

Intl.Collator().compare

Intl.Collator().compare を使うとより細かくソートできます。

const list = ['項目10', '項目300', '項目3']

list.sort(new Intl.Collator('ja', {numeric: true}).compare)

console.log(list)  // ['項目3', '項目10', '項目300']

numeric オプションを有効にすると数字つきの文字をソートできます。また、巨大な配列の場合は localeCompare() よりも高速になります。

const dimensions = [
  '10cm × 20cm',
  '30cm × 20cm',
  '30cm* × 15cm',
  '100cm × 120cm',
  '50cm × 50cm',
  '30cm × 40cm',
]

dimensions.sort(new Intl.Collator('ja', {numeric: true}).compare)

console.log(dimensions)
// ['10cm × 20cm', '30cm × 20cm', '30cm × 40cm', '30cm* × 15cm', '50cm × 50cm', '100cm × 120cm']

dimensions.sort(new Intl.Collator('ja', {numeric: true, ignorePunctuation: true}).compare)

console.log(dimensions)
// ['10cm × 20cm', '30cm* × 15cm', '30cm × 20cm', '30cm × 40cm', '50cm × 50cm', '100cm × 120cm']

また、寸法のソートにも使えます。ignorePunctuation オプションを有効にするとアスタリスクなどの句読点を無視できます。

逆順のソート

逆順にソートするときは reverse() 関数を使うのではなく、マイナス演算子を用いてソートすると効率がよいです。

const names = ['Éthan', 'Oliver', 'Elijah', 'みなと', 'はるき', 'いつき']

names.sort((a, b) => -a.localeCompare(b))

console.log(names)  // ['みなと', 'はるき', 'いつき', 'Oliver', 'Éthan', 'Elijah']

const dimensions = [
  '10cm × 20cm',
  '30cm × 20cm',
  '30cm* × 15cm',
  '100cm × 120cm',
  '50cm × 50cm',
  '30cm × 40cm',
]

dimensions.sort((a, b) => -new Intl.Collator('ja', {numeric: true, ignorePunctuation: true}).compare(a, b))

console.log(dimensions)
// ['100cm × 120cm', '50cm × 50cm', '30cm × 40cm', '30cm × 20cm', '30cm* × 15cm', '10cm × 20cm']

10. 正規表現と後方参照

正規表現内で \N と記述すると N 番目のキャプチャを参照できます。\2 なのでこの場合は ["'] が参照され、2 種類の引用符どちらにも対応できるようになります。

const regex = /([\w-]+)=(["'])(.+?)\2/

regex.exec(`data-attr="value"`)
// ["data-attr="value"", "data-attr", """, "value"]

regex.exec(`data-attr='value'`)
// ["data-attr="value"", "data-attr", "'", "value"]

regex.exec(`data-attr="value'`)
// null

regex.exec(`data-attr='value"`)
// null

また、(?<名前>正規表現) でキャプチャ範囲に名前をつけることができ、\k<名前> で後方参照できます。groups プロパティに名前をキーとしたオブジェクトとして格納されます。

const regex = /(?<attr>[\w-]+)=(?<delim>["'])(?<value>.+?)\k<delim>/

regex.exec(`data-attr="value"`).groups
// {attr: "data-attr", delim: """, value: "value"}

regex.exec(`data-attr='value'`).groups
// {attr: "data-attr", delim: "'", value: "value"}

11. JParticles

軽量なパーティクルライブラリです。

https://github.com/Barrior/JParticles

12. moovie.js

依存なしで字幕などのカスタマイズ性能が高い HTML5 動画プレイヤーライブラリです。

https://github.com/BMSVieira/moovie.js

13. winbox

Windows や MacOS のウィンドウのように Web ページ上で自由に移動や拡大縮小できるウィンドウを実装できるライブラリです。

https://github.com/nextapps-de/winbox

14. cheetah-grid

Canvas を使って大量のデータを Web 上でテーブルとして表示できるライブラリです。

https://github.com/future-architect/cheetah-grid

15. aladino

ハイクオリティな WebGL のエフェクトライブラリです。

https://github.com/luruke/aladino

16. gpu.js

GPU のパワーを使って処理を高速化できるライブラリです。

https://github.com/gpujs/gpu.js

17. 開発者専用ブラウザResponsively

色んな画面幅での表示を 1 つの画面上で確認できる開発者専用ブラウザです。

  • スクロールなどの動作が同期
  • 配置などもカスタマイズ可能
  • Chrome DevTools 搭載
  • 好きなデバイスを追加可能
  • ボタン 1 つでスクリーンショット
  • ホットリロード対応

https://responsively.app/

18. Cumulative Layout Shift Debugger

URL を入力するだけで CLS のデバッグができるオンラインツールです。

https://webvitals.dev/cls

19. SVG Crop

SVG 画像の周りの余分な余白を削除できるオンラインジェネレーターです。

https://svgcrop.com/

20. Theme Studio for VSCode

Web 上で VSCode のテーマを作成できるオンラインジェネレーターです。

https://themes.vscode.one/

No.8 ← | → No.10


今すぐ使えるCSSレシピブック

Discussion

ログインするとコメントできます