【html,css,javascript】tableの列を動的に表示・非表示切り替え

はじめに

技術的に久しぶりに躓いたので、記事にまとめます。簡単な解説と私がなぜこの列の表示・非表示を使いたいかの背景にも触れます。良かったら読んでみてください!

想定読者

  1. html・css・javascriptについて聞いたことがある人・興味がある人

  2. tableの列の表示・非表示を実装したい人

  3. ※私がなぜこの技術を使いたいかを知りたい人(GAS関連)



実装編

完成イメージ


完成イメージ:チェックボックスをクリックすることで隠れていた列が表示される

ちなみにテーブルの中身は、今は懐かしいゲーム、ロマンシング・サガ3の男性主人公のデータです。

htmlとcssのみで実装した場合 全コード

<html>
<head>
    <style>
        td,th{
            border:1px black solid;
        }
        col.collapse{
            visibility: collapse;
        }
        #checkbox1:checked ~ table colgroup col.collapse{
            visibility: visible;
        }
    </style>
</head>
<body>
    <input type="checkbox" id="checkbox1">
    <label for="checkbox1">詳細</label>
    <table>
        <colgroup>
            <col></col>
            <col class="collapse"></col>
            <col class="collapse"></col>
            <col class="collapse"></col>
            <col></col>
        </colgroup>
        <tr>
            <th>名前</th>
            <th>年齢</th>
            <th>性別</th>
            <th>宿星</th>
            <th>武器</th>
        </tr>
        <tr>
            <td>ユリアン</td>
            <td>20</td>
            <td>男性</td>
            <td>歳星</td>
            <td>剣</td>
        </tr>
        <tr>
            <td>トーマス</td>
            <td>22</td>
            <td>男性</td>
            <td>辰星</td>
            <td>槍</td>
        </tr>
        <tr>
            <td>ハリード</td>
            <td>33</td>
            <td>男性</td>
            <td>太白</td>
            <td>剣</td>
        </tr>
        <tr>
            <td>ミカエル</td>
            <td>27</td>
            <td>男性</td>
            <td>鎮星</td>
            <td>小剣</td>
        </tr>
    </table>
</body>
</html>

javascriptで実装した場合 全コード

<html>
<head>
    <script>
        function showDetail(){
            const checkbox = document.getElementById("checkbox1");
            let visibility_value = "collapse";
            if(checkbox.checked){
                visibility_value = "visible";
            }
            const elements = document.getElementsByClassName("collapse");
            for(let i = 0 ; i < elements.length; i++){
                elements[i].style.visibility = visibility_value;
            }
        }
    </script>
    <style>
        td,th{
            border:1px black solid;
        }
        col.collapse{
            visibility: collapse;
        }
    </style>
</head>
<body>
    <input type="checkbox" id="checkbox1" onchange="showDetail()">
    <label for="checkbox1">詳細</label>
    <table>
        <colgroup>
            <col></col>
            <col class="collapse"></col>
            <col class="collapse"></col>
            <col class="collapse"></col>
            <col></col>
        </colgroup>
        <tr>
            <th>名前</th>
            <th>年齢</th>
            <th>性別</th>
            <th>宿星</th>
            <th>武器</th>
        </tr>
        <tr>
            <td>ユリアン</td>
            <td>20</td>
            <td>男性</td>
            <td>歳星</td>
            <td>剣</td>
        </tr>
        <tr>
            <td>トーマス</td>
            <td>22</td>
            <td>男性</td>
            <td>辰星</td>
            <td>槍</td>
        </tr>
        <tr>
            <td>ハリード</td>
            <td>33</td>
            <td>男性</td>
            <td>太白</td>
            <td>剣</td>
        </tr>
        <tr>
            <td>ミカエル</td>
            <td>27</td>
            <td>男性</td>
            <td>鎮星</td>
            <td>小剣</td>
        </tr>
    </table>
</body>
</html>

※どちらも、全文をメモ帳(notepad)にコピーして、拡張子を.htmlとして保存すれば、動作します。
※詳しく調べていないので分かりませんが、ブラウザによっては対応していないかも・・・。動かなかったらごめんなさい。


解説編

かんたんな解説(css)

visibilityのプロパティをvisibleとcollapseに切り替えることでテーブルの列の表示・非表示を切り替えることができます。(※もちろん、技術的に行の表示・非表示も可能です。)テクニック的には、テーブルにcolタグを用いることで、列全体にcssを反映させることができます。
技術的に引っかかった個所は、

#checkbox1:checked ~ table colgroup col.collapse{
 visibility: visible;
}

のtable colgroup col.collapseという指定の仕方です。tableタグの下のcolgroupタグの下のcolタグ内のcollapseクラスの指定を意味しています。
:checked ~ 要素でチェックがされている場合の時のみに有効な要素のcssを指定することができます。

#checkbox1:checked ~ col.collapse{
 visibility: visible;
}

上はダメな例です。動きません。なぜかというと、~セレクタ(間接セレクタ)は同じ階層からしか指定できないためです。colタグはinputタグと同じ階層にいないので参照できないのです。
つまり、

<input>
<table>
 <colgroup>
  <col></col>
 </colgroup>
</table>

上のようにinputタグと同じ階層のtableタグから実際に影響させたいcolタグまでをたどって指定する必要があるのです。イメージとしては、相対パス参照のような感じです。
ちなみに、

<div>
 <input>
</div>
<table>
 <colgroup>
  <col></col>
 </colgroup>
</table>

のようにinputタグをdivタグやpタグで囲ってしまうと、もう動きません。そのようにしたい場合は、javascriptでの実装が良いでしょう。cssは上部側へさかのぼって指定することはできないそうです。

かんたんな解説(javascript)

javascriptで書いてあるだけではなく、html側にも以下のような変更があります。

<input type="checkbox" id="checkbox1" onchange="showDetail()">

inputにonchange属性をつけて、関数名はなんでも良いのですが、ここでは、showDetail(詳細表示の意味)としています。※本当は切り替えるというような名前の方がよかったかも・・・。
javascriptの実装個所です。

function showDetail()
 const checkbox = document.getElementById("checkbox1");
 let visibility_value = "collapse";
 if(checkbox.checked){
  visibility_value = "visible";
 }
 const elements = document.getElementsByClassName("collapse");
 for(let i = 0 ; i < elements.length; i++){
  elements[i].style.visibility = visibility_value;
 }
}

モダンな書き方は知らないので、レトロな書き方です。
動作(トリガー)はチェックボックスの値を変更した時(onchange)に動作します。

流れとしては、以下になります。

  1. checkboxをidを使って取得

  2. visibilityの値をcheckboxの状態によって変更したいので、可変な変数(visibility_value)を宣言

  3. checkboxの状態(チェックされているかどうか)によってvisibility_valueを変更

  4. 表示・非表示を設定したいcol(列)をクラス名を指定して取得 ※複数、今回は3個取得される

  5. 取得したcol要素の数だけ以下の処理

  6. 取得したcol要素のvisibilityをvisivility_valueに変える

注意点としては、classで指定するので(※もちろんidで指定してもOK。その場合は、単数になる)、複数のcol要素に対してstyleの書き換えが必要ということ。


私がこの技術を使いたいと思ったかんたんな背景

私は、GAS(Google Apps Script)を用いて開発をすることが多いです。このGASはGoogleが提供しているので、もちろんGoogleのサービスとすごく相性がいいです。特にスプレッドシートを用いるといろんなことができます。

私の業務としてスプレッドシートをデータベースとして用いることが多いのですが、社内向けの情報の場合、情報の閲覧性(誰にどこまで見せるか)が問題になることが多いです。まぁ、権限・役職に応じた閲覧性で問題無い(ロジックが組みやすい)のですが、たくさんのスプレッドシートを用意するよりも、一枚のスプレッドシートで閲覧をコントロールする方が何かと都合が良い場合が多いのです。
その制御のためにもWEBアプリ(GASの機能の一つとして提供されている)で制御するのが、かんたんです。WEBアプリには、バックエンドとフロントエンドが存在します。バックエンドでフィルターをかけて情報を絞り込むことができます。フロントエンドはhtmlで書くことができます。
WEBアプリはPCはもちろん、スマホでもアクセスできます。つまり、スマホも考慮する必要があるのです。
スマホは縦長の画面で横が狭いです。そのため、横長のデータを表示するのは厳しいと思いました。そのため、列の表示・非表示を用いることで、横の長さを制御しようと思ったのです。

補足ですが、もちろん、テーブルによるデータ表示の生成は、javascriptによる動的生成をしています。


最後に

最後まで読んでいただいてありがとうございました。

この記事が気に入ったらサポートをしてみませんか?