Help us understand the problem. What is going on with this article?

jsを使ったツールチップ(ピン止め可)をcssだけで実装する

More than 1 year has passed since last update.

少し時間があったので数年前に作った管理画面のソースを眺めてたんですが
「あれ?このscript、全部cssでかけるんじゃね?」
「このscriptなくなれば、このページjqueryの読み込みいらないじゃん・・・」
ということがあり・・・

まぁ当時はあまりcssはそんなに明るくなくて・・・ゴニョゴニョ

で、どんなscriptなのかというと
マウスを載せる(乗せる?)とツールチップが表示される
まぁよくあるアレですw
「バルーン」ですね。

仕様(一応)

  • マウスを載せるとツールチップを表示する。
  • ツールチップに出ている文字をクリップボードにコピーできるようにツールチップをピン止めできるようにする
  • ピン止めしたツールチップは外すことができる

こんな感じです。

ピン止めの方法はクリックにしました。
クリックすることでピン止めされ、ピン止めすると枠色を変化させて、ユーザはピン止めしているかを知る。
再クリックでピン止めが外され、枠色も戻る。

サンプルをざくっと作ったのでbefore-afterを全文載せときます。
細かい部分でミスがあったら見逃して下さいw
(一応チェックしてますけど・・)

Before

  • 画面
    tooltip_before.png

  • ソース

before.html
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
    <title>自作ツールチップテスト</title>
    <script src="jquery.min.js" type="text/javascript"></script>
    <script language="JavaScript">
    $(document).ready(function() {
        $(".has_detail").hover(
            function(){
                $(this).children(".detail_info").show();
            },
            function(){
                $(this).children(".detail_info").not(".always").hide();
            }
        );
        $(".has_detail").click(
            function(){
                var tips = $(this).children(".detail_info");
                if(!$(tips).hasClass("always")){
                    $(tips).addClass("always");
                }
            }
        );
        $(".detail_info").click(
            function(){
                $(this).removeClass("always");
                return false;
            }
        );
    });
    </script>
<style>
* {
  margin: 0;
}
ul {
  list-style: none;
}
p.title {
  font-weight: bold;
  color: #000099;
}
div.contents {
  border: none;
  min-height: 750px;
  background-color: #ffffff;
  padding: 8px 16px;
}
div.contents > div {
  margin-top: 30px;
}
div.contents > div:first-child {
  margin-top: 10px;
}
div#goods_list > ul {
  display: table;
  border-collapse: collapse;
  width: 100%;
}
div#goods_list > ul > li {
  display: table-row;
  line-height: 2.0em;
}
div#goods_list > ul > li > ul {
  display: table-cell;
  padding-left: 20px;
}
div#goods_list > ul > li > ul > li {
  display: inline-block;
}
div#goods_list span.goods_no {
  display: inline-block;
  width: 30px;
  text-align: center;
}
ul#list_data span.goods_detail {
  display: inline-block;
  width: 100px;
  text-align: center;
  background-color: #bbccff;
  position: relative;
}
ul#list_data span.goods_detail:hover {
  background-color: #ff8c00;
  cursor: pointer;
}
div#goods_list li.goods_name,li.goods_price,li.goods_open,li.goods_memo {
  width: 160px;
  text-align: center;
}
ul#list_header > li {
  background-color: #E0F2F7;
  border-bottom: 1px solid #000;
}
ul#list_data > li {
  border-bottom: 1px solid #059;
}
ul#list_data > li:hover {
  background-color: #dce5f4;
}
span.detail_info {
  background: antiquewhite;
  border: 2px solid #fc6;
  position: absolute;
  top: 15;
  left: -225;
  text-align: center;
  padding: 10px 12px;
  z-index: 2;
  display: none;
}
span.detail_info.always {
  border-color: #f60;
}
</style>
</head>
<body>
<div class="contents">
  <div id="goods_list">
    <p class="title">商品一覧</p>
    <hr/>
    <ul id="list_header">
      <li>
        <span class="goods_no"></span>
        <ul>
          <li class="goods_name">商品名</li>
          <li class="goods_price">価格</li>
          <li class="goods_open">販売日</li>
          <li class="goods_memo"></li>
        </ul>
      </li>
    </ul>
    <ul id="list_data">
      <li>
        <span class="goods_no">1</span>
        <ul>
          <li class="goods_name">勉強机A</li>
          <li class="goods_price">20000</li>
          <li class="goods_open">2016/02/01</li>
          <li class="goods_memo"></li>
        </ul>
        <span class="goods_detail has_detail">詳細表示
        <span class="detail_info">
          <table style="width : 200px; margin-left: auto; margin-right: auto;">
          <tr>
            <th>日付</th>
            <th>内容</th>
          </tr>
          <tr>
            <td>2016/04/01</td>
            <td>在庫切れ</td>
          </tr>
          </table>
        </span></span>
      </li>
      <li>
        <span class="goods_no">2</span>
        <ul>
          <li class="goods_name">勉強机B</li>
          <li class="goods_price">20000</li>
          <li class="goods_open">2016/02/01</li>
          <li class="goods_memo"></li>
        </ul>
        <span class="goods_detail">詳細表示</span>
      </li>
      <li>
        <span class="goods_no">3</span>
        <ul>
          <li class="goods_name">勉強机C</li>
          <li class="goods_price">20000</li>
          <li class="goods_open">2016/02/01</li>
          <li class="goods_memo"></li>
        </ul>
        <span class="goods_detail hasDetail">詳細表示</span>
      </li>
    </ul>
  </div>
</div>
</body>

After

  • 画面
    tooltip_after.png
    beforeと同じかw

  • ソース

after.html
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
    <title>自作ツールチップテスト</title>
    <script src="jquery.min.js" type="text/javascript"></script>
    <script language="JavaScript">
    $(document).ready(function() {
        //$(".has_detail").hover(
        //  function(){
        //      $(this).children(".detail_info").show();
        //  },
        //  function(){
        //      $(this).children(".detail_info").not(".always").hide();
        //  }
        //);
        //$(".has_detail").click(
        //  function(){
        //      var tips = $(this).children(".detail_info");
        //      if(!$(tips).hasClass("always")){
        //          $(tips).addClass("always");
        //      }
        //  }
        //);
        //$(".detail_info").click(
        //  function(){
        //      $(this).removeClass("always");
        //      return false;
        //  }
        //);
    });
    </script>
<style>
* {
  margin: 0;
}
ul {
  list-style: none;
}
p.title {
  font-weight: bold;
  color: #000099;
}
div.contents {
  border: none;
  min-height: 750px;
  background-color: #ffffff;
  padding: 8px 16px;
}
div.contents > div {
  margin-top: 30px;
}
div.contents > div:first-child {
  margin-top: 10px;
}
div#goods_list > ul {
  display: table;
  border-collapse: collapse;
  width: 100%;
}
div#goods_list > ul > li {
  display: table-row;
  line-height: 2.0em;
}
div#goods_list > ul > li > ul {
  display: table-cell;
  padding-left: 20px;
}
div#goods_list > ul > li > ul > li {
  display: inline-block;
}
div#goods_list span.goods_no {
  display: inline-block;
  width: 30px;
  text-align: center;
}
ul#list_data label.goods_detail {
  display: inline-block;
  width: 100px;
  text-align: center;
  background-color: #bbccff;
  position: relative;
}
ul#list_data label.goods_detail:hover {
  background-color: #ff8c00;
  cursor: pointer;
}
div#goods_list li.goods_name,li.goods_price,li.goods_open,li.goods_memo {
  width: 160px;
  text-align: center;
}
ul#list_header > li {
  background-color: #E0F2F7;
  border-bottom: 1px solid #000;
}
ul#list_data > li {
  border-bottom: 1px solid #059;
}
ul#list_data > li:hover {
  background-color: #dce5f4;
}
span.detail_info {
  background: antiquewhite;
  border: 2px solid #fc6;
  position: absolute;
  top: 15;
  left: -225;
  text-align: center;
  padding: 10px 12px;
  z-index: 2;
  display: none;
}
span.detail_info.always {
  border-color: #f60;
}
input[type="checkbox"] {
  display: none;
}
input[type="checkbox"]:not(:checked) + .has_detail .detail_info {
  border-color: #fc6;
  display: none;
}
input[type="checkbox"]:not(:checked) + .has_detail:hover .detail_info {
  display: inline;
}
input[type="checkbox"]:not(:checked) + .has_detail:not(:hover) .detail_info {
  display: none;
}
input[type="checkbox"]:checked + .has_detail .detail_info {
  border-color: #f60;
  display: inline;
}
</style>
</head>
<body>
<div class="contents">
  <div id="goods_list">
    <p class="title">商品一覧</p>
    <hr/>
    <ul id="list_header">
      <li>
        <span class="goods_no"></span>
        <ul>
          <li class="goods_name">商品名</li>
          <li class="goods_price">価格</li>
          <li class="goods_open">販売日</li>
          <li class="goods_memo"></li>
        </ul>
      </li>
    </ul>
    <ul id="list_data">
      <li>
        <span class="goods_no">1</span>
        <ul>
          <li class="goods_name">勉強机A</li>
          <li class="goods_price">20000</li>
          <li class="goods_open">2016/02/01</li>
          <li class="goods_memo"></li>
        </ul>
        <input type="checkbox" id="goods_no_1">
        <label for="goods_no_1" class="goods_detail has_detail">詳細表示
        <span class="detail_info">
          <table style="width : 200px; margin-left: auto; margin-right: auto;">
          <tr>
            <th>日付</th>
            <th>内容</th>
          </tr>
          <tr>
            <td>2016/04/01</td>
            <td>在庫切れ</td>
          </tr>
          </table>
        </span></label>
      </li>
      <li>
        <span class="goods_no">2</span>
        <ul>
          <li class="goods_name">勉強机B</li>
          <li class="goods_price">20000</li>
          <li class="goods_open">2016/02/01</li>
          <li class="goods_memo"></li>
        </ul>
        <input type="checkbox" id="goods_no_2">
        <label for="goods_no_2" class="goods_detail">詳細表示</label>
      </li>
      <li>
        <span class="goods_no">3</span>
        <ul>
          <li class="goods_name">勉強机C</li>
          <li class="goods_price">20000</li>
          <li class="goods_open">2016/02/01</li>
          <li class="goods_memo"></li>
        </ul>
        <input type="checkbox" id="goods_no_3">
        <label for="goods_no_3" class="goods_detail hasDetail">詳細表示</label>
      </li>
    </ul>
  </div>
</div>
</body>

jqueryを外す前で、scriptをコメントアウトしてる状態です。

ポイントてきなもの

見えないチェックボックスを作って
チェック状態の場合は表示、非チェック状態の場合は非表示
という感じになります。
ラベルを使ってチェックボックスする感じですかね。

~略~

input[type="checkbox"] {
  display: none;
}
input[type="checkbox"]:not(:checked) + .has_detail .detail_info {
  border-color: #fc6;
  display: none;
}
input[type="checkbox"]:not(:checked) + .has_detail:hover .detail_info {
  display: inline;
}
input[type="checkbox"]:not(:checked) + .has_detail:not(:hover) .detail_info {
  display: none;
}
input[type="checkbox"]:checked + .has_detail .detail_info {
  border-color: #f60;
  display: inline;
}

~略~

追加したのはここの部分ですね。
あとはspanをlabelにしているだけになります。

最後に・・

ピン止め設定/解除のクリックがafterだとツールチップ上でも可能という
違いはありますが、こっちの方が使い勝手がよいので・・・ヨシとさせてくださいませ。

また、ツールチップ内の文字をコピペしやすいように
詳細表示とツールチップのブロックを少し重ねてあります。

以上、自分用メモですが皆さんのご参考になれば。

n_a
java屋です。 でもここでは備忘録という感じで java以外のことをメインに書いていきたいです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした