質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.34%

  • JavaScript

    11222questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    4898questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • CSS

    3874questions

    CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

  • CSS3

    1478questions

    CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

CSS/javascript はみ出た要素を縮小し、画面ぴったりに表示したい

解決済

回答 2

投稿 2017/11/26 00:13 ・編集 2017/11/26 00:35

  • 評価
  • クリップ 0
  • VIEW 367

nnahito

score 1411

 行いたいこと

table要素で縦横にはみ出た場合、セルの大きさの比率を変えずに縮小し、
画面に収めたい。
イメージ説明

 質問

テーブルの、セルの大きさの比率を変えずにブラウザの画面に収めたいと考えております。
しかし、以下のようなコードを書いても表示が乱れるだけでした。

<table id="element"></table>

※↑<td>タグは省略

$(document).ready(function(){

    // ウインドウのサイズ
    let window_width = $(window).width();

    // セルの幅
    let cell_width = $('#element td').width();

    // テーブルの幅
    table_width = cell_width * 100;

    // テーブルの幅を拡張
    $('#element').css('width', table_width);

    // 横スクロールの幅取得
    let scrollsize = document.body.scrollWidth;

    let zoom = window_width / scrollsize;

    // 画面いっぱいになるまで、ズームアウト
    $('#element').css('transform', 'scale('+ zoom +', 1)');

});

乱れた感じ

イメージ説明

これは何故でしょうか?
利用ブラウザは、
Firefox Developer Edition 58.0b6(64bit)
です。

どのようにすれば縮小がうまくいくか、ご存じの方がいらっしゃいましたらご教示いただけますと幸いです。

 追記

HTML/CSS/JSの全文

呼んでいるJSライブラリ

  • jQuery
  • riot ( http://riotjs.com/ja/ )
  • lattice ( https://github.com/nnahito/lattice )
<!DOCTYPE html>
<html lang="ja">

<head>
    <title></title>
    <meta charset="UTF-8">

    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script src="lattice.js?a"></script>

    <style>

    div{
        margin: 5px;
    }

    #element {
        border: 1px #e0e0e0 solid;
        table-layout: fixed;
    }

    #element td{
        border: 1px #e0e0e0 solid;
        width: 50px !important;
        height: 50px;
        text-align: center;
        vertical-align: middle;
    }

    .no-place{
        background-color: #e0e0e0;
    }

    </style>

</head>

<body>

    <div>
        <button id="add_row">行を追加</button>
        <button id="add_col">列を追加</button>
        <button id="del_row">行を削除</button>
        <button id="del_col">列を削除</button>
        <br>
        <button id="get_table">中身を取得</button>
        <br>
        <label>
            <input type="checkbox" id="no-place">灰色にする
        </label>
    </div>

    <hr>

    <table id="element">

    </table>

    <hr>
    <div id="out_json_text"></div>


    <script>
    var $Lattice;


    $(document).ready(function(){

        $Lattice = new Lattice('#element', 'a', 100, 100);
        $Lattice.initialize();

        // ウインドウのサイズ
        let window_width = $(window).width();

        // セルの幅
        let cell_width = $('#element td').width();

        // テーブルの幅
        table_width = cell_width * 100;

        // テーブルの幅を拡張
        $('#element').css('width', table_width);

        // 横スクロールの幅取得
        let scrollsize = document.body.scrollWidth;

        let zoom = window_width / scrollsize;

        // 画面いっぱいになるまで、ズームアウト
        //$('#element').css('transform', 'scale('+ zoom +', 1)');
        //
        // console.log(scrollsize);
        // console.log(window_width);
        // console.log(zoom);

    });


    /**
     * 行を追加
     */
    $('#add_row').on('click', function(){
        $Lattice.addRow();
    });


    /**
     * 列を追加
     */
    $('#add_col').on('click', function(){
        $Lattice.addCol();
    });


    /**
     * 行を削除
     */
    $('#del_row').on('click', function(){
        $Lattice.removeRow();
    });


    /**
     * 列を削除
     */
    $('#del_col').on('click', function(){
        $Lattice.removeCol();
    });


    /**
     * データを保存
     */
    $('#get_table').on('click', function(){
        let json = $Lattice.get();

        $('#out_json_text').text(JSON.stringify(json));
    });


    /**
     * セルがクリックされたとき
     */
    $(document).on('click', '#element td', function(){

        // 灰色にするボタン
        if ( $('#no-place').prop('checked') ){
            $(this).addClass('no-place');
        } else {
            $(this).removeClass('no-place');
        }



    });
    </script>

</body>
</html>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2017/11/26 00:31

    CSSやHTMLを省略されてしまうと状況の再現が出来ません。追記していただけませんか?

    キャンセル

  • nnahito

    2017/11/26 00:35

    ご指摘ありがとうございます。追記させていただきました

    キャンセル

回答 2

+4

横100個の要素ならそうなると思います。

  1. scale(0.233048, 1)このようになって縦横比がおかしくなる
  2. borderも1px以下になるため表示されない(ことがある)

動くサンプル:https://jsfiddle.net/8vaprgh9/

やり方に無理が有ると思います。

投稿 2017/11/26 01:05

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/26 01:33

    ご回答ありがとうございます。

    > やり方に無理が有る
    なるほど、そういうことだったのですね……
    こちら、どのようなアイデアで解決を行えばよいでしょうか?
    もしご存知でしたらそちらもご教授いただけますと幸いです。

    キャンセル

  • 2017/11/26 01:43

    テーブルの中身次第ですが、スクロールするか、テーブル自体の組み方を変えてしまう(コンテンツによってはテーブルを使わないことも)のが手早いと思います。

    文字がセルの中に入るのであれば、文字が6pxを下回ると表示がうまくいかない(可読性が無い)可能性が高くなります。文字が無いのであれば罫線ではなく面で表現する(背景色を交互にするなど)ほうが縮小には向きます。

    キャンセル

  • 2017/11/26 11:18

    ご返信ありがとうございます。

    > テーブル自体の組み方を変えてしまう
    なるほど……構成を変えないと難しい感じですね。。。

    > 文字がセルの中に入るのであれば、文字が6pxを下回ると表示がうまくいかない
    > 文字が無いのであれば罫線ではなく面で表現する
    こちら、Excelで作っていた座席システムをWebで表示する仕組みにしようと思っております。
    席数も多いので拡大縮小で全体を見やすくしたいなーと……
    なので、この方法しか思いつかずやや困っております。

    キャンセル

  • 2017/11/26 23:30

    今の方法では、例えば320px幅のモバイル端末で見た場合、1セルあたり2px(罫線抜いて3px)しか表示できません。色分けで席の位置関係がわかればよいなど、それで問題が無いものであれば画面幅に合わせて情報を減らしていけばよいかもしれません。

    別の方法としては、映画館のチケットや航空券のチケットのように、「座席全体⇒タッチした周辺の席」という感じに 2~3段階くらいに拡大表示する方法。

    上記とほぼ同じですが、GoogleMapのような拡大縮小インターフェイスで全体を見せるとか。(下記は画像を表示していますが、3段階の座席表をHTMLで作ってMapインターフェイスで動かすことも可能です)

    【Extending Leaflet, New Layers - Leaflet - a JavaScript library for interactive maps】
    http://leafletjs.com/examples/extending/extending-2-layers.html

    キャンセル

  • 2017/11/28 14:36

    ご返信ありがとうございます。

    > GoogleMapのような拡大縮小インターフェイスで全体を見せる
    私もこちらをイメージしておりました。
    こちらはやはり画像でないと難しいのでしょうか?

    キャンセル

  • 2017/11/28 15:29

    > こちらはやはり画像でないと難しいのでしょうか?
    HTMLを出すことも出来ると思いますよ。(未調査ですが、GoogleMapsAPIで5年ほど前にそういう実装をしたことがあります。同種のライブラリとして出来ると思います)

    キャンセル

  • 2017/11/28 15:47

    GridLayer がそれっぽいですね。

    【Documentation - Leaflet - a JavaScript library for interactive maps】
    http://leafletjs.com/reference-1.2.0.html#gridlayer

    キャンセル

  • 2017/11/30 16:35

    ご返信ありがとうございます。
    申し訳ありませんが、英語なのでよくわかりませんでした……
    結局描画したいHTMLはどこで渡すのでしょうか?
    いただいたGridLayerのオプション部分にも渡せそうなあたいはなさそうでした。

    一応、以下、テストで作ってみましたが、結局画像しか表示できずに断念しました。
    どこにHTMLをかけば良いのでしょうか?

    <!DOCTYPE html>
    <html>
    <head>
    <title>GridLayer Test</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />
    <style>
    body {
    padding: 0;
    margin: 0;
    }
    html, body, #map {
    height: 100%;
    width: 100%;
    }
    </style>
    </head>
    <body>

    <div id="map"></div>





    <script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>
    <script>

    // 表示する場所
    var map = new L.Map('map', { center: [10, 0], zoom: 2});

    // 表示する内容を作成(レイヤー作成)
    var tiles = new L.GridLayer();

    var CanvasLayer = L.GridLayer.extend({
    // レイヤーの定義(coordsはどこで使ってんの?)
    createTile: function(coords){
    // キャンバス作成
    var tile = L.DomUtil.create('canvas', 'leaflet-tile');

    // サイズの取得
    var size = this.getTileSize();
    tile.width = size.x;
    tile.height = size.y;

    // 2Dオブジェクト
    var ctx = tile.getContext('2d');

    return tile;
    }
    });

    // マップを読み込んでる?
    // ここで必要HTMLを入れる処理を書く?
    //L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {}).addTo(map)
    L.gridLayer();

    // 要素に描画
    tiles.addTo(map);


    </script>
    </body>
    </html>

    キャンセル

  • 2017/11/30 17:34

    このあたりのコードを参考にしてみてください。基本的に行っていることは同じです。

    【L.GridLayerでコピペ可能なタイル座標の表示 - monomotiの日記】
    http://monomoti.hatenablog.jp/entry/ac2016

    【TileCoordsTile/app.js at master · monomoti/TileCoordsTile · GitHub】
    https://github.com/monomoti/TileCoordsTile/blob/master/js/app.js

    キャンセル

  • 2017/11/30 18:19

    ご回答ありがとうございます。

    > このあたりのコードを参考にしてみてください。基本的に行っていることは同じです。
    とのことでしたので、
    L.tileLayer('./check.html', {}).addTo(map)
    とやってみるとメモリオーバーになりました。。。(画面は灰色のままです)

    キャンセル

  • 2017/11/30 18:42

    L.tileLayer('./check.html', はどこから来たのかわかりませんが、まずはサンプルをそのまま動かしながら変更すべき点を考えたほうが良いと思います。

    https://jsfiddle.net/vfbda7ge/

    日本語での情報が少ないため、英語が読めないならこのライブラリは使えないと見て別の手段を検討されることをお勧めします。(私はGoogleMapsAPIでの実装経験があったため「どう組めばどこに出力がでるか」がなんとなくわかりますが、元々地図表現ライブラリなので実装に向いているわけでは有りません)

    キャンセル

  • 2017/11/30 19:13

    もともとがHTMLの拡大縮小を目指していたので、実験を試みております。
    サンプルを動かして、実際マップの表示はできておりますが、どのサンプルも結局画像の拡大縮小をおこなっていて、私の行いたい物がありません。

    > 日本語での情報が少ないため、英語が読めないならこのライブラリは使えないと見て別の手段を検討されることをお勧めします
    ここまでお付き合い頂いて申し訳ございませんが、時間がないための質問のため、このライブラリの利用は見送らせていただきます。(もちろん時間があれば使ってみたかったですが…)

    ありがとうございました。

    キャンセル

checkベストアンサー

0

 calc()

calc() で計算してやれば、内容の最小幅に反しない範囲でなら実現可能な気がします。
動的に要素ノードを追加するなら、width プロパティ値も動的に算出してやる必要はあります。

<style>
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
}
#sample {
  margin: 0;
  padding: 0;
  width: calc(100% - 2px);
  border: 1px black solid;
  border-collapse: separate;
  border-spacing: 1px;
}

#sample td {
  background-color: #eef;
  border: 1px black solid;
  width: calc(100%-200px);
  overflow: hidden;
  height: 50px;
  text-align: center;
  vertical-align: middle;
}
</style>
</head>
<body>
<table id="sample">
  <tbody>
    <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
  </tbody>
</table>

 動的計算のコード

tableは自動的に等間隔の幅に合わせる為、アスペクト比だけ合わせれば、期待通りに動作するようです。

下記コードは widthheight 以外のプロパティ値(borderfont-size等)は元の値を維持します。
必要であれば、setStyleRule() の適用範囲を広げて下さい。

<style>
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
}

#sample {
  margin: 0;
  padding: 0;
  width: calc(100% - 2px);
  border: 1px black solid;
  border-collapse: separate;
  border-spacing: 1px;
}

#sample td {
  background-color: #eef;
  border: 1px black solid;
  text-align: center;
  vertical-align: middle;
}
</style>
</head>
<body>
<form id="table-setting">
  <p><label>縦横比(縦/横) <input type="number" name="aspect-ratio" value="1"></label></p>
  <p><label>列数 <input type="number" name="cells-length" value="5"></label></p>
  <p><label>行数 <input type="number" name="rows-length" value="5"></label></p>
</form>
<table id="sample">
  <tbody>
    <tr><td></td></tr>
  </tbody>
</table>
<script>
'use strict';
(function () {
  function setStyleRule (doc, selectorText, property, value) {
    var styleSheets = doc.styleSheets,
        styleSheetslength = styleSheets.length,
        i = 0,
        cssRules, cssStyleRule, cssRulesLength, j;

    while (i < styleSheetslength) {
      cssRules = styleSheets[i++].cssRules;
      cssRulesLength = cssRules.length;
      j = 0;

      while (j < cssRulesLength) {
        cssStyleRule = cssRules[j++];

        if (cssStyleRule.selectorText === selectorText) {
          cssStyleRule.style[property] = value;
          return;
        }
      }
    }
  }

  function handleInputAspectRatio (event) {
    var input = event.target,
        aspectRatio = input.valueAsNumber,
        doc = input.ownerDocument,
        td = doc.getElementById('sample').tBodies[0].rows[0].cells[0],
        width = doc.defaultView.getComputedStyle(td, '').width;

    setStyleRule(doc, '#sample td', 'height', parseFloat(width) * aspectRatio + 'px');
  }

  function handleInputRowsLength (event) {
    var input = event.target,
        length = input.valueAsNumber,
        tbody = input.ownerDocument.getElementById('sample').tBodies[0],
        rows = tbody.rows,
        rowsLength = rows.length,
        tr;

    if (length === rowsLength) {
      return;
    }

    if (length > rowsLength) {
      tr = rows[0];

      while (rowsLength++ < length) {
        tbody.appendChild(tr.cloneNode(true));
      }
    } else {
      while (rowsLength > length) {
        tbody.removeChild(rows[--rowsLength]);
      }
    }

    handleInputAspectRatio({target: input.form.elements['aspect-ratio']});
  }

  function handleInputCellsLength (event) {
    var input = event.target,
        length = input.valueAsNumber,
        doc = input.ownerDocument,
        tbody = doc.getElementById('sample').tBodies[0],
        rows = tbody.rows,
        rowsLength = rows.length,
        tr = rows[0],
        cells = tr.cells,
        cellsLength = cells.length,
        td, df, i;

    if (length === cellsLength) {
      return;
    }

    if (length > cellsLength) {
      td = cells[0];
      df = doc.createDocumentFragment();

      while (cellsLength++ < length) {
        df.appendChild(td.cloneNode(true));
      }

      i = 0;

      while (i < rowsLength) {
        rows[i++].appendChild(df.cloneNode(true));
      }
    } else {
      while (rowsLength) {
        tr = rows[--rowsLength];
        i = cellsLength;

        while (length < i) {
          tr.deleteCell(--i);
        }
      }
    }

    handleInputAspectRatio({target: input.form.elements['aspect-ratio']});
  }


  function main () {
    var elements = this.document.getElementById('table-setting').elements,
        aspectRatio = elements['aspect-ratio'],
        rowsLength = elements['rows-length'],
        cellsLength = elements['cells-length'];

    aspectRatio.addEventListener('input', handleInputAspectRatio, false);
    rowsLength.addEventListener('input', handleInputRowsLength, false);
    cellsLength.addEventListener('input', handleInputCellsLength, false);

    handleInputAspectRatio({target: aspectRatio});
    handleInputRowsLength({target: rowsLength});
    handleInputCellsLength({target: cellsLength});
  }

  main.call(this);
}.call(this));
</script>

Re: nnahito さん

投稿 2017/11/27 00:02

編集 2017/11/27 02:08

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.34%

関連した質問

同じタグがついた質問を見る

  • JavaScript

    11222questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    4898questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • CSS

    3874questions

    CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

  • CSS3

    1478questions

    CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。