web-dev-qa-db-ja.com

マウスでCSSグリッドレイアウトの列を動的にサイズ変更する

列区切り線をドラッグして(またはプレースホルダーのサイズを変更して)CSSグリッドレイアウトボックスのサイズを動的に変更しようとしています。

nav要素にresize: horizontal;を設定してサイズを変更し、要素の右下隅にある小さなサイズ変更ハンドルをドラッグするとサイズが変更されますが、隣接する列の幅は自動的に調整されません重複につながります。壊れた codepen があります。

[〜#〜] html [〜#〜]

<main>
 <nav>#1</nav>
 <header>#2</header>
 <section>#3</section>
</main>

[〜#〜] css [〜#〜]

main {
    display: grid;
    border: 3px dotted red;
    grid-gap: 3px;
    grid-template-columns: 200px 1fr;
    grid-template-rows: 100px 1fr;
    height: 100%;
}

nav {
    grid-column: 1;
    grid-row: 1;
    grid-row: 1 / span 2;
    resize: horizontal;
    overflow: scroll;
    border: 3px dotted blue;
}

私はcssグリッドエンジンがこのケースを自動的に処理することを期待していましたが、明らかにそうではありません。

jquery-ui resizable を試しましたが、CSSグリッドではうまく機能しないようです。

グリッド属性grid-template-columns/rows:を動的な値に設定してjqueryでそれを行う方法を検討していますが、サイズ変更ハンドルを介して要素のサイズを変更することによってスローされるイベントをキャッチする方法は明確ではありません。 jquery resize イベントはwindowオブジェクトでのみトリガーされ、dom要素ではトリガーされません。

Dragstart/dragendのような低レベルのマウスイベントを処理せずにそれを行う方法は何でしょうか。

13
ccpizza

あなたが達成しようとしていることは、CSSのみを使用して可能です。あなたの例を修正しました。主なポイントは次のとおりです。

  1. 最も重要なのは、セマンティックレイアウトタグに生のコンテンツを挿入しないようにしてください。テキストおよびbrタグではなく、ヘッダー、段落、およびリストタグを使用します。これにより、コードが読みやすくなり、推論しやすくなります。問題の多くは、グリッド領域でのリフローの処理方法が原因で発生しました。
  2. Grid-templateを使用すると、後でブレークポイントのリフローが簡単になるため、レイアウトを簡素化できます。
  3. オーバーフローを使用:自動;サイズ変更の指定とともに:垂直/水平。オーバーフローを設定しないと、サイズ変更は失敗します。
  4. サイズ変更の境界を作成するには、最小/最大幅/高さの値を使用します。
body {
    margin: 10px;
    height: 100%;
}

main {
    display: grid;
    border: 3px dotted red;
    padding: 3px;
    grid-gap: 3px;
    
    grid-template: 
    "nav head" min-content
    "nav main" 1fr
        / min-content 1fr;
}

nav {
    grid-area: nav;
    border: 3px dotted blue;
    overflow: auto;
    resize: horizontal;
    
    min-width: 120px;
    max-width: 50vw;
}

header {
    grid-area: head;
    border: 3px dotted orange;
    overflow: auto;
    resize: vertical;
    
    min-height: min-content;
    max-height: 200px;
}

section {
    grid-area: main;
    border: 3px dotted gray;
}
<main>
  <nav>
    <ul>
      <li>Nav Item</li>
      <li>Nav Item</li>
      <li>Nav Item</li>
      <li>Nav Item</li>
      <li>Nav Item</li>
      <li>Nav Item</li>
    </ul>
  </nav>

  <header>
    <h1>Header Title</h1>
    <small>Header Subtitle</small>
  </header>

  <section>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </section>
</main>
7
baetheus

解決策は、not明示的な固定列サイズ(grid-template-columns: 200px 1fr;)を使用するが、代わりに使用することですgrid-template-columns: 0.2fr 1fr;などの相対的な列サイズ—グリッドCSSエンジンは、隣接するボックスのサイズ変更を処理します。次に、グリッドボックス内にネストされたdivを追加し、min-height/widthを100%に設定し、 jqueryui resizable を使用してサイズ変更可能にします。

修正された jsfiddle

/* Javscript */

$('.left_inner').resizable();
$('.right_top_inner').resizable();
$('.right_bottom_inner').resizable();
/* CSS */

        .grid {
                display: grid;
                grid-template-columns: 0.2fr 1fr;
                grid-template-rows: 1fr 4fr;
        grid-gap: 3px;
                position: relative;
        }

        .left {
                grid-row: 1 / span 2;
        }

        .right_top {
                grid-column: 2;
                grid-row: 1;
        }

        .right_bottom {
                grid-column: 2;
                grid-row: 2;
        }

        .left_inner {
                background-color: #fedcd2;
                padding: 0;
                width: 100%;
                min-width: 100%;
                height: 100%;
                min-height: 100%;
                text-align: center;
        }

        .right_top_inner {
                background-color: #f9cf00;
                padding: 0;
                width: 100%;
                min-width: 100%;
                height: 100%;
                min-height: 100%;
                text-align: center;
        }

        .right_bottom_inner {
                background-color: #f8eee7;
                padding: 0;
                width: 100%;
                min-width: 100%;
                height: 100%;
                min-height: 100%;
                text-align: center;
        }
<!-- HTML -->

<script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.0/css/smoothness/jquery-ui-1.10.0.custom.min.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.0/jquery-ui.js"></script>

        <main class="grid">
         <aside class='left'>
          <div class="left_inner">
                drag the bottom right handle to resize
          </div>
         </aside>
         <section class="right_top">
          <div class="right_top_inner">right_top_inner</div>
         </section>
         <section class="right_bottom">
          <div class="right_bottom_inner">right_bottom_inner</div>
         </section>
        </main>

❗️これは可能な限り単純なシナリオでは機能しますが、実際の使用例では問題が生じます。私は jquery-ui layout を試しましたが、これはいくぶん良く機能しました(ここでは demo です)が、ライブラリは古く、フレームに不具合があるため、 angle-split-pane (angular 1に基づく)これは正常に動作し、サイズが小さくなります。 (更新:プロジェクトは現在放棄されているようで、おそらく最良の選択ではないようです)

4
ccpizza