uga.dev

小技・小ネタ

公開日:

最終更新:

HTML/CSS/JavaScriptやブラウザ周りの覚えておくと便利なテクニック、共有したい小ネタをまとめます。

メニュー

Webという言葉の表記

本サイトでは「Web」という表記で統一しています。

参考:「Webという言葉の表記が揺れている

CSS

1つのHTMLに施された200種類以上のスタイリング例

CSS Zen Garden

2003年にDave Shea氏が立ち上げたデザイン投稿サイトです。同一のHTMLファイルに対してCSSのみを変更した例が200種類以上公開されており、HTMLとCSSの分離やWeb標準の考え方を広く普及させるきっかけのひとつとなりました。

rebeccapurpleという色名

CSSのサンプルコード
* {
  color: rebeccapurple;
}

CSSコミュニティで長年活躍されているEric Meyer氏のご息女、Rebecca Alison Meyerさんが6歳の誕生日に亡くなったことを受け、Rebeccaさんが好きだった紫色を彼女の名前で残そうという呼びかけが起こり、rebeccapurpleCSS Color Module Level 4に追加されました[1]。のちにCSS-Nextコミュニティが公開したCSSのロゴにも、このrebeccapurpleが採用されています。

JavaScript

JavaScriptは[ ] ( ) ! +の6つの記号だけでコードが書ける

たとえば!![]trueになり、+[]は「0」、+!+[]は「1」になります。

JSのサンプルコード
console.log(!![]);                       // > true
console.log(+[]);                        // > 0
console.log(+!+[]);                      // > 1
console.log((!![]+[])[+[]]);             // > t
console.log((!![]+[])[+!+[]]);           // > r
console.log((!![]+[])[!+[]+!+[]]);       // > u
console.log((!![]+[])[!+[]+!+[]+!+[]]);  // > e

文字列化した"true" "false" "undefined" "[object Object]"などからアルファベットを拾ってeval()する、というテクニック(?)です[2]

alert(1)を実行するコード
[][(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[+!+[]]]+[+!+[]]+([]+[]+[][(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[!+[]+!+[]]])

JavaScriptコードそのものがアスキーアートになっている芸術がある

aem1k - JS Hacks & Creativity

実行すると地球が回り出すSpin the globeだけでも見てほしい[3]

NaNNaNと等しくない

NaNは自分と比べても等しくない唯一の値です。0/0'hoge' * 2など、異なる計算でも無効な結果はすべてNaNになります。それらを同じ値とみなさないようにするため、ECMAScript仕様(IEEE 754準拠)でこのように定められています[4]

JSのサンプルコード
console.log(null === null);           // > true
console.log(undefined === undefined); // > true
console.log(true === true);           // > true
console.log(1 === 1);                 // > true
console.log(Infinity === Infinity);   // > true
console.log(NaN === NaN);             // > false

ただし、後述のSameValueZero比較を使うArray.prototype.includes()や、SameValue比較を使うObject.is()であれば、NaN同士を等しいものとして扱えます。

JSのサンプルコード
console.log([NaN].find(item => item === NaN)); // > undefined
console.log([NaN].some(item => item === NaN)); // > false
console.log([NaN].includes(NaN));              // > true
console.log(Object.is(NaN, NaN));              // > true

なお、ある値がNaNであるかを判定したいときはNumber.isNaN()を使います。globalThis.isNaN()は引数を数値に変換してから判定するため、isNaN('NaN')trueになるなど直感的ではない結果が返ることがあります。

JSのサンプルコード
// Not a Numberかどうかを確認してる
console.log(isNaN(1));            // > false
console.log(isNaN("NaN"));        // > true
console.log(isNaN(NaN));          // > true

// 値が NaN であるかを確認してる
console.log(Number.isNaN(1));     // > false
console.log(Number.isNaN("NaN")); // > false
console.log(Number.isNaN(NaN));   // > true

JavaScriptには等価比較のアルゴリズムが4種類ある

抽象等価と厳密等価以外にも、Array.prototype.includes()Map/Setのキー比較で使われるSameValueZeroObject.is()で使われるSameValueがあります[5]

違いはNaN同士と+0/-0の扱いだけです。

アルゴリズム使われる場所NaNNaNの比較+0-0の比較
抽象等価 (Loose Equality)==falsetrue
厳密等価 (Strict Equality)===falsetrue
SameValueZeroArray.prototype.includes()Map/Setのキー比較などtruetrue
SameValueObject.is()truefalse
JSのサンプルコード
console.log(NaN === NaN);          // > false
console.log(+0 === -0);            // > true

// SameValueZero
console.log([NaN].includes(NaN));  // > true
console.log([+0].includes(-0));    // > true

// SameValue
console.log(Object.is(NaN, NaN));  // > true
console.log(Object.is(+0, -0));    // > false

0.1 + 0.20.3にならない

0.1 + 0.2の計算結果は0.30000000000000004になります。

JSのサンプルコード
console.log(0.1 + 0.2);         // > 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // > false

十進の小数を正確に表せないために生じる誤差で、JavaScriptに限らず多くの言語で同じことが起こります[6]

document.allはfalsy

document.allはすべての要素を含むHTMLAllCollectionを返しますが、オブジェクトでありながら真偽値に変換するとfalseになる唯一の値です。型もobjectではなくundefinedです。

JSのサンプルコード
console.log(Boolean(document.all));                     // > false
console.log(document.all instanceof HTMLAllCollection); // > true
console.log(typeof document.all);                       // > "undefined"

かつてInternet Explorerを判定するためにif (document.all)のような分岐がよく書かれていました。こうした既存のコードがモダンブラウザで壊れないよう、willful violation意図的な仕様違反として定められています[7]

undefinedNaNInfinityはリテラルではない

truenullなどと異なり、undefinedNaNなど一部の値はwindowに変数として用意されているだけ。

JSのサンプルコード
console.log('undefined' in window, window.undefined); // > true, undefined
console.log('NaN' in window, window.NaN);             // > true, NaN
console.log('Infinity' in window, window.Infinity);   // > true, Infinity

console.log('null' in window, window.null);           // > false, undefined
console.log('true' in window, window.true);           // > false, undefined

かつて変数undefinedは上書き可能だったため、undefinedとの比較はtypeofを使うか、undefinedを返すvoid 0と比較していました。

hogeがundefinedであるかどうかを検証する例
if (typeof hoge === 'undefined') {}
if (hoge === void 0) {}

ローカルスコープでは、現代でも変数名として宣言できるので、ES3時代の雰囲気を味わうことができます。

undefinedがundefinedではなくなる例
((undefined, NaN, Infinity) => {
  console.log(undefined, NaN, Infinity); // > 0, 1, 2
})(0, 1, 2);
nullやtrueは予約語なのでSyntaxErrorになる
const undefined = true; // OK
const null = true;      // SyntaxError
const true = false;     // SyntaxError

id属性をもつHTML要素はグローバル変数に公開される

とくに活用するタイミングはないですが、id属性を持つ要素が読み込まれるとグローバル変数として公開されます。たとえばスクリプト実行時点でDOMにdiv#hogeが存在すると、window.hogeHTMLDivElementを返します。

HTMLのサンプルコード
<script>
console.log(window.hoge);          // > undefined
console.log(window['my-element']); // > undefined
</script>

<div id="hoge"></div>
<div id="my-element"></div>

<script>
console.log(hoge);                  // > HTMLDivElement
console.log(window['my-element']);  // > HTMLDivElement
</script>

動画を2倍速以上で再生する裏技

倍速設定のUIがなくても早くできる。

JSのサンプルコード
document.querySelector('video').playbackRate = 3

動画をピクチャーインピクチャー再生する裏技

PiPのUIがなくてもPiPできる。

JSのサンプルコード
document.querySelector('video').requestPictureInPicture()

出典