2026/03/05(木)HTMLの標準機能でカラーパレットを使ったカラーコード入力UIを作る方法

投稿日:

なんかこんな感じのやつの作り方。

内容

左側にあるカラーパレットを出すボタンはinput type="color"で実現できるので、単純なカラー入力だけならこれでも構わない。現時点ではAndroid版Firefoxを除き、主要ブラウザは

ただ、コードも欲しいことが往々だと思うので、その場合は横にinput type="text"を生やして、次に示すサンプルコードのように双方の入力値をバインディングしてやればよい。

サンプルコード

動きはデモページで確認できる。

<input id="palette" type="color">
<input id="code" type="text">
<script>
  const getInput = () => {
    return {
      palette: document.getElementById('palette'),
      code: document.getElementById('code')
    };
  };

  const registerHandlers = (paletteEl, codeEl) => {
    paletteEl.addEventListener('input', (e) => {
      codeEl.value = e.target.value;
    });
    codeEl.addEventListener('input', (e) => {
      paletteEl.value = e.target.value;
    });
  };

  window.addEventListener('DOMContentLoaded', () => {
    const input = getInput();
    registerHandlers(input.palette, input.code);
  });
</script>

Safariでも表示できるが見た目がだいぶ異なる

PC Safari 18.2とiOS 26.3のSafariで確認した見た目。

一行目が初期表示、二行目がカラーパレット展開表示。iOS Safariの方は素の状態だとUIが小さすぎて見えないので、かなり拡大して表示している。

PC Safari iOS Safari
PC Safari初期表示
iOS Safari初期表示
PC Safariカラーパレット展開表示
iOS Safariカラーパレット展開表示

2025/09/11(木)アクセシブルなトグルボタンをHTMLとCSSで書く

更新日:
投稿日:

こんな感じにフォーカスが当たるとOS標準の枠が出て、矢印キーの左右で選択状態を切り替えられる<input type="radio" />要素の作り方。

大まかには<label><input type="radio" /></label>の構造にして、UI上はラベルを疑似要素的に表示し、ラジオボタン本体はUI上見えなくするが、display: none;にせず、画面に残すことによってタブ遷移できるフォーカス可能要素として設計する内容。

サンプルコード

デモページ

CSS

/* ラジオボタンを等間隔に整列し、左右に余計な空白を持たせない */
.radio-container {
    display: flex;
    column-gap: 0.25rem;
}

.hidden-radio {
    /* チェックを消す */
    appearance: none;

    /* 非推奨要素を使っているが、iOS Safari対策 */    
    position: absolute;
    clip: rect(0, 0, 0, 0);
    pointer-events: none;
    
    /* デフォルトマージンがチェックボックスの位置にあるので消す */
    margin: 0;
}

.radio-label {
    /* 文字列要素を綺麗に中央寄せする */
    display: flex;
    justify-content: center;
    align-items: center;

    /* 枠装飾、基本的にフォーカス枠が角丸であり、違和感がないようにborderも角丸にしておく */
    padding: 5px;
    border: 1px solid #60bce9;
    border-radius: 4px;

    /* 見かけ上ボタンなのでカーソルをボタン用にする */
    cursor: pointer;
}

/* ラジオチェック時にラベルの背景色を変化させる */
.radio-label:has(.hidden-radio:checked) {
    background-color: #60bce9;
}

/* ラジオフォーカス時にラベルのフォーカス枠を出す */
.radio-label:has(.hidden-radio:checked):focus-within {
    outline: auto;
}

HTML

<form>
    <div class="radio-container">
        <label class="radio-label">
            <input name="r2" type="radio" class="hidden-radio" value="1" checked />
            <span>道明寺</span>
        </label>
        <label class="radio-label">
            <input name="r2" type="radio" class="hidden-radio" value="2" />
            <span>長命寺</span>
        </label>
    </div>
</form>

2024/11/13(水)imgタグで画像が取得できなかった時に代替画像を表示する

投稿日:

事前にバイナリをHTTPクライアントで取得してハンドリングするのかと思っていたが、実際にはimgタグのonerrorイベントでハンドリングできた。

確認環境

Microsoft Edge 130.0.2849.56

サンプルコード

<html>
<head>
  <script>
    function handleError(ev) {
      ev.target.src="https://example.com/empty.gif";
    }
  </script>
</head>
<body>
  <img src="https://example.jp/hoge.jpg" onerror="handleError(event)" />
</body>
</html>

最初に考えていたコード

これでも同じようなことはできるにはできるが、CORSやlazy loadとか考えると面倒で、コードも増えるし、採用するメリットはあんまりないと思う。

<html>
<head>
  <script>
    window.onload = () => {
      const img = document.getElementById('img');

      fetch('https://example.jp/hoge.jpg')
        .then((res) => {
          if (res.status === 200) {
              res.blob().then((data) => {
                img.src = URL.createObjectURL(data);
              }).catch(() => {
                img.src = 'https://example.com/empty.gif';
              });
            } else {
              img.src = 'https://example.com/empty.gif';
            }
        }).catch(() => {
          img.src = 'https://example.com/empty.gif';
        });
    }
  </script>
</head>
<body>
  <img id="img" />
</body>
</html>

2024/03/21(木)textareaみたいなUIをアクセシビリティに配慮した実装で作る

投稿日:

昔のサイトには以下のように、更新履歴を書く用途でtextarea要素が使われていたことがよくあったと思う。

<TEXTAREA>== 2024/01/15 ==
ギャラリーにイラストを一点追加

== 2024/01/01 ==
トップページを更新</TEXTAREA>

しかし、これをLighthouseで見るとアクセシビリティ違反になることがある(labelがないとか言われる)。label要素を使うのも一つの手だが、使わずやる場合にどう回避するかというのを紹介する。

以下は実装の一例だ。

<div style="resize: vertical; border: 1px solid #ccc; overflow-y: scroll; height: 5rem; min-height: 5rem;"><small><pre>== 2024/01/15 ==
ギャラリーにイラストを一点追加

== 2024/01/01 ==
トップページを更新</pre></small></div>

textareaみたいなUI

描画サンプルとしては、このような形になる。

内容的にはよくあるoverflow: scrollなコンテナだが、ポイントは"resize: vertical;height: 5rem; min-height: 5rem;だ。"resize: vertical;によってtextareaの様に拡縮可能なUIを提供できるようにしている。height: 5rem; min-height: 5rem;は標準の高さと最低の高さを両方指定することで、UI縮小時にUIが潰れてしまうのを防いでいる。

そもそもlabelがあった方が見やすいし、何かが分かりやすいというのはそうなのだが、なんか中二病みたいなレイアウトにしたいとか、そもそもフォームではなく、単なる表示枠なのでからlabelを使いたくないとかいうケースで有用になるだろう。

2024/02/12(月)さくらのレンタルサーバーでSSIを使う

更新日:
投稿日:

そういやSSI使ったことなかったなと思ったので。

やり方

  1. .shtmlを作る
  2. CGI・PHP・SSI を利用したい | さくらのサポート情報の書式を見てコードを書く

任意の処理結果を出させる例

現在の年を出す場合のやり方

  1. 以下の内容でhoge.plを作成

    #!/usr/local/bin/perl
    
     print qx(date "+%Y");
    
  2. chmod 705 hoge.pl
  3. 以下の内容でpiyo.shtmlを作成
    <!--#exec cmd="./hoge.pl"-->
    

注意点

同一パスにあるコマンドしか実行できないため、以下のような内容は動かない

グローバルなコマンドは動かない

<!--#exec cmd="date +%Y"-->

こんなことをしても動かない

<!--#echo VAR="date +%Y"-->

サブシェルを書いても動かない

<!--#echo VAR="$(date +%Y)"-->

参考