HTMLとCSSで、引き出しから自分が飛び出す仕掛けを作ってみた


こんなことを試しました。

リンクにカーソルを重ねると、引き出しが動いてアバターがひょこっと登場。HTMLとCSSのサンプルを動かしながら作れます。

公開サイトで検証・動くデモと全コードあり

ブログの引き出しからアバターと紙が飛び出した画面
ブログの引き出しからアバターと紙が飛び出した画面
動くデモを触ってみる ↗
この記事の目次

白い背景は好き。でも、ちょっとおとなしいな……。

「りゅうのらぼ」のホームを作るとき、そんなところから見た目を調整していきました。きれいに並んでいるだけより、おもちゃ箱みたいに、触ると何か起きる場所にしたい。

そこで引き出し型のリンクに、アバターが出てくる仕掛けを入れています。今回は公開中のページを実際に操作しながら、どう見えるか確かめてみました。

閉じているときは、普通に読める入口に

普段はこんな見た目です。プロフィール、おしごと、ブログ、SNS、日記。どこへ行くかは、何もしなくても読めます。

アバターが隠れている通常時の5つの引き出し
通常時の実画面。動く部分だけでなく、行き先のラベルも残しています。

引き出しは、ページへ移動するためのリンクです。飛び出す演出が分からなくても、押したら目的のページへ行ける。その土台に、少しだけ遊びを足しています。

触れると、箱がずれて顔が出る

「ブログ」の引き出しにフォーカスを移してみると、枠が少しずれ、その上からアバターと紙が出てきました。

ブログの引き出しからGitHubの顔画像を使ったアバターと紙が出た状態
今回はキーボードのTabキーで操作して撮影。青い枠はフォーカスの表示です。カーソルを重ねる場合も同じ表示切り替えを使っています。

顔はGitHubのプロフィール画像。体と腕は別の小さなパーツです。全部を一枚の絵にして動かすのではなく、顔・体・小物を組み合わせています。

最初に引き出しが動いて、その少しあとに顔が出る。ぴったり同時に動くよりも、ひょこっと反応した感じにしたかった部分です。

中身を見てみると、意外と地味な仕組み

立体の箱を用意しているわけではありません。実装を確認すると、引き出しの位置を左へ9px、下へ3pxずらし、影の位置も変えています。

アバターは、普段は下へ隠しておいて、反応すると上へ移動させる仕組み。出てくるときの動き方を少し弾むように調整しています。

コードの量を見せるより、まずは画面で「何が違うか」を見たほうが伝わりそうだったので、今回の写真は同じページの通常時と反応した状態にしました。

別の引き出しも見てみた

続いて「おしごと」へフォーカスを戻すと、紙の代わりにパソコンが出てきます。

おしごとの引き出しにフォーカスを当てたホームの実画面
おしごとの実画面。アバターの横にパソコンが現れます。こちらもキーボード操作で確認しました。

実装上は、プロフィールでは手を振り、日記では鉛筆が書くように動く、といった違いも付けています。今回写真にしたのは、おしごととブログの2種類です。

動けばいい、というわけでもなさそう

画面を確認していて、アバターは引き出しの上側へ出るので、ひとつ上の引き出しに重なることも分かります。遊びを足した分だけ、文字の読みやすさも見ておきたいところです。

また、スマートフォンにはマウスのカーソルがありません。動きを見せることだけを前提にせず、普段からラベルを読めるようにしています。今回の検証はPC上のキーボード操作で、スマートフォンでのタップ操作を実機検証した記録ではありません。

ちょっとした仕掛けですが、「ここ、触ると何か出るんだ」と気付いてもらえると楽しそう。そんな寄り道を、少しずつ増やしていければと思います。

実際の「らぼのひきだし」を開く

確認日:2026年11月4日。スクリーンショットは公開サイトを実際に操作して撮影。仕組みはホームのコードとアバターのコードで照合しました。

同じものを作るなら、まずこの1ファイルで試してみる

ここからは自分のサイトに入れてみたい方向けです。まずは本番の仕掛けを小さくしたサンプルを作りました。必要なのはテキストエディタとブラウザだけ。Node.jsやライブラリのインストールは不要です。

動くサンプルを開く / HTMLをZIPでダウンロード

本番は「押すと移動するリンク」ですが、このサンプルはスマートフォンでも動きを試せるように、「押すと開く引き出し」と「中にあるリンク」に分けています。顔は配布しやすい絵文字です。

  1. 下のコードをすべてコピーします。
  2. エディタで index.html という名前のUTF-8のプレーンテキストファイルに保存します。末尾が .html.txt にならないようにします。Macのテキストエディットを使う場合は「フォーマット」→「標準テキストにする」を選びます。
  3. 保存したファイルをブラウザで開きます。
  4. 引き出しにカーソルを重ねて顔が出るか確認。次にクリックして中のリンクを開きます。
  5. Tabキーで引き出しを選び、Enterで開閉できるかも試します。スマートフォンではタップで開閉します。
配布用HTMLを実際にブラウザで開き、引き出しを開いた画面
配布コードそのものをブラウザで実行。クリックで開き、Enterで閉じることを確認しました。

そのまま動くHTML・CSS

以下がサンプルの全コードです。長めですが、まず丸ごと動かしてから、下で説明する3か所だけ変えると追いやすいと思います。

<!doctype html>
<html lang="ja">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>飛び出す引き出し・最小サンプル</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 32px 20px; color: #303d48; background: #fff;
  font-family: system-ui, sans-serif; line-height: 1.8; }
main { max-width: 540px; margin: auto; }
h1 { font-size: 26px; }
.cabinet { padding: 85px 24px 24px; background: #eee9df;
  border: 2px solid #303d48; border-radius: 16px; }
.drawer { --color: #fff0b8; position: relative; }
.drawer summary { position: relative; padding: 24px; list-style: none;
  border: 2px solid #303d48; border-radius: 8px; background: var(--color);
  box-shadow: 0 5px 0 #303d48; cursor: pointer;
  transition: transform .2s, box-shadow .2s; }
.drawer summary::-webkit-details-marker { display: none; }
.drawer summary::after { content: '▰'; float: right; }
.drawer summary:focus-visible { outline: 3px solid #315f91; outline-offset: 5px; }
/* 上側は空ける。隠すのはキャラクター用の窓だけ。 */
.window { position: absolute; right: 18px; top: -72px; width: 84px;
  height: 72px; overflow: hidden; pointer-events: none; }
.avatar { display: block; font-size: 54px; text-align: center;
  transform: translateY(80px); opacity: 0;
  transition: transform .5s .1s cubic-bezier(.2,1.5,.4,1), opacity .2s; }
.drawer:is(:hover, :focus-within, [open]) summary {
  transform: translate(-6px, 2px); box-shadow: 6px 7px 0 #303d48; }
.drawer:is(:hover, :focus-within, [open]) .avatar {
  transform: translateY(0); opacity: 1; }
.contents { margin-top: 18px; padding: 16px; background: #fff;
  border-radius: 8px; }
a { color: #245b89; }
#destination { margin-top: 36px; padding: 20px; background: #eef5ef; }
@media (prefers-reduced-motion: reduce) {
  .drawer summary, .avatar { transition: none; }
}
</style>
<main>
  <h1>引き出しを、ひとつ作ってみる。</h1>
  <p>カーソルを重ねると顔が出ます。クリック・タップ・Enterで開閉できます。</p>
  <div class="cabinet">
    <details class="drawer">
      <summary>
        <span class="window" aria-hidden="true"><span class="avatar">🙂</span></span>
        ブログのひきだし
      </summary>
      <div class="contents"><a href="#destination">記事の置き場所へ進む →</a></div>
    </details>
  </div>
  <section id="destination"><h2>記事の置き場所</h2><p>ここまで移動できれば、リンクも動いています。</p></section>
</main>
</html>

自分のサイト用に変えるのは、まず3か所

  • 名前:ブログのひきだし を表示したい言葉へ。
  • 行き先:href="#destination" を自分のブログURLへ。確認用の section id="destination" は、その後削除して構いません。
  • 色:--color: #fff0b8 を好みの色へ。文字とのコントラストも確認してください。

自分のアバターにしたいときは、HTMLと同じフォルダーへ avatar.png を置き、絵文字の span を次の画像に置き換えます。

<img class="avatar" src="avatar.png" alt="" width="64" height="64">

CSSには .avatar { width: 64px; height: 64px; object-fit: cover; margin: 4px auto; } を追加します。画像は装飾なので、この例では空のaltにしています。名前やリンク先は画像の外に文字で残します。

なぜ動く? ここだけ分かれば調整できる

translateY(80px) で顔を窓の下へ隠し、反応したら translateY(0) へ戻しています。transition は、その移動を一瞬ではなく時間をかけて見せる設定です。

:hover はカーソル、:focus-within はキーボード操作、[open] は開いた状態への対応。details と summary の標準機能を使うため、開閉用のJavaScriptはありません。

動きを減らす設定では transition: none にしています。開閉できることはそのままで、移動アニメーションを省きます。

表示がおかしいときに見るところ

  • 顔が出ない:引き出しや外側の箱に overflow: hidden を付けていないか確認。隠すのは .window の中だけです。
  • 画像だけ出ない:avatar.png の名前・拡張子・保存場所が合っているか確認。
  • リンク先へ進めない:このサンプルは一度開いてから、中のリンクを押します。summaryは移動ボタンではありません。
  • 別の引き出しの文字に重なる:複数並べる場合は上に顔が出る分の余白を取ります。まず margin-top: 85px を目安に調整してください。

完成の確認:顔が出る/クリックやEnterで開閉する/中のリンクで移動する。この3つを自分の環境でも確認できたら、最初のひとつは完成です。