【html,css,javascript】tableの列を動的に表示・非表示切り替え
はじめに
技術的に久しぶりに躓いたので、記事にまとめます。簡単な解説と私がなぜこの列の表示・非表示を使いたいかの背景にも触れます。良かったら読んでみてください!
想定読者
html・css・javascriptについて聞いたことがある人・興味がある人
tableの列の表示・非表示を実装したい人
※私がなぜこの技術を使いたいかを知りたい人(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)に動作します。
流れとしては、以下になります。
checkboxをidを使って取得
visibilityの値をcheckboxの状態によって変更したいので、可変な変数(visibility_value)を宣言
checkboxの状態(チェックされているかどうか)によってvisibility_valueを変更
表示・非表示を設定したいcol(列)をクラス名を指定して取得 ※複数、今回は3個取得される
取得したcol要素の数だけ以下の処理
取得したcol要素のvisibilityをvisivility_valueに変える
注意点としては、classで指定するので(※もちろんidで指定してもOK。その場合は、単数になる)、複数のcol要素に対してstyleの書き換えが必要ということ。
私がこの技術を使いたいと思ったかんたんな背景
私は、GAS(Google Apps Script)を用いて開発をすることが多いです。このGASはGoogleが提供しているので、もちろんGoogleのサービスとすごく相性がいいです。特にスプレッドシートを用いるといろんなことができます。
私の業務としてスプレッドシートをデータベースとして用いることが多いのですが、社内向けの情報の場合、情報の閲覧性(誰にどこまで見せるか)が問題になることが多いです。まぁ、権限・役職に応じた閲覧性で問題無い(ロジックが組みやすい)のですが、たくさんのスプレッドシートを用意するよりも、一枚のスプレッドシートで閲覧をコントロールする方が何かと都合が良い場合が多いのです。
その制御のためにもWEBアプリ(GASの機能の一つとして提供されている)で制御するのが、かんたんです。WEBアプリには、バックエンドとフロントエンドが存在します。バックエンドでフィルターをかけて情報を絞り込むことができます。フロントエンドはhtmlで書くことができます。
WEBアプリはPCはもちろん、スマホでもアクセスできます。つまり、スマホも考慮する必要があるのです。
スマホは縦長の画面で横が狭いです。そのため、横長のデータを表示するのは厳しいと思いました。そのため、列の表示・非表示を用いることで、横の長さを制御しようと思ったのです。
補足ですが、もちろん、テーブルによるデータ表示の生成は、javascriptによる動的生成をしています。
最後に
最後まで読んでいただいてありがとうございました。