No.9 2021年4月にツイートしたHTML/CSS/JavaScriptのTipsまとめ
2021 年 4 月にツイートした HTML/CSS/JavaScript のツイートまとめです。見出しをクリックするとツイート元に遷移するので、気に入ったらフォロー・ファボ・リツイートお願いします。
SVGとCSSでファビコン
1.<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>">
:is()セレクタの便利な使い道
2.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()
セレクタを使えばまとめて記述できるようになります。
CSS Logical Properties のショートハンド
3.CSS Logical Properties は LTR / RTL(右から左に書く言語)両方に対応するときに便利なプロパティです。それに加え、既存のいくつかのプロパティをまとめて宣言できるショートハンドプロパティも追加されています。
inset
プロパティ
inset
プロパティは、top
right
bottom
left
プロパティのショートハンドです。
.selector {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.selector {
position: absolute;
inset: 0;
}
margin-inline
プロパティ
margin-inline
プロパティは、margin-left
margin-right
プロパティのショートハンドです。
.selector {
margin-left: auto;
margin-right: auto;
}
.selector {
margin-inline: auto;
}
CSS変数に関するクイズ
4.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 でアンケートしてみたところ、 綺麗に red
と blue
に割れました。答えは blue
です。
--bg-color
が定義された時点で、--default-color
は定義されていないため、フォールバック値の blue
が採用されます。CSS 変数は値が継承される前に解決されるので注意が必要です。
半透明な線の縁取り
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
このメソッドは非推奨のようです。
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) // 👨
絵文字とUnicode
7.コード値の取得
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
ラベル
break
と for
文の前に記述できるラベルを使えば多重ループを抜けられます。
// 対象の配列
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"}
JParticles
11.軽量なパーティクルライブラリです。
moovie.js
12.依存なしで字幕などのカスタマイズ性能が高い HTML5 動画プレイヤーライブラリです。
winbox
13.Windows や MacOS のウィンドウのように Web ページ上で自由に移動や拡大縮小できるウィンドウを実装できるライブラリです。
cheetah-grid
14.Canvas を使って大量のデータを Web 上でテーブルとして表示できるライブラリです。
aladino
15.ハイクオリティな WebGL のエフェクトライブラリです。
gpu.js
16.GPU のパワーを使って処理を高速化できるライブラリです。
開発者専用ブラウザResponsively
17.色んな画面幅での表示を 1 つの画面上で確認できる開発者専用ブラウザです。
- スクロールなどの動作が同期
- 配置などもカスタマイズ可能
- Chrome DevTools 搭載
- 好きなデバイスを追加可能
- ボタン 1 つでスクリーンショット
- ホットリロード対応
Cumulative Layout Shift Debugger
18.URL を入力するだけで CLS のデバッグができるオンラインツールです。
SVG Crop
19.SVG 画像の周りの余分な余白を削除できるオンラインジェネレーターです。
Theme Studio for VSCode
20.Web 上で VSCode のテーマを作成できるオンラインジェネレーターです。
Discussion