【问题标题】:CSS Grid Ignores Max HeightCSS Grid 忽略最大高度
【发布时间】:2021-11-10 20:16:51
【问题描述】:

我有一个用于 nonogram 应用程序的复杂布局网格,对于不同大小的网格应该是灵活的。非图如下所示,并且不保证内部网格具有任何特定的大小或列与行的比率。此外,行和列的标题将包含未知数量的元素

在较小的屏幕上,我的应用看起来不错,并且网格缩小了;但是当你增加尺寸时,一旦你达到了应该限制高度的点,网格反而会扩展以用尽其所有可用宽度,同时保持其其他比例并吹出底部。

正在发生的事情的 GIF:https://ibb.co/YfsT8nL

该问题的一些附加草图:

我尝试了很多不同的方法来限制布局,但似乎没有任何效果。似乎包含网格的元素的大小将达到我想要的限制,但随后 #cell-container 爆炸了,然后爆炸了 #grid-container,然后爆炸并溢出了 #game-container

我所做的唯一似乎实际上可以做任何事情的事情是直接调整#cell-container 的大小,但这不是解决方案,因为这样外部网格将无法正确调整大小以保持标题对齐并使网格居中.

我期望的行为是将行标题和列标题的大小设置为min-content,然后cells 网格区域应该调整要包含的单元格的大小。

来自我的应用程序的代码(使用 Svelte、TailwindCSS 编写)

// NonoGame.svelte
<div id="game-container" class="flex flex-col px-2 h-screen">
    <div id="game-header" class="flex flex-shrink-0 flex-grow-0 items-center justify-end text-3xl">
        <GameTimer />
        <PauseButton {controller} />
    </div>

    <div class="flex-shrink my-auto">
        <div class="h-auto">
            <NonoGrid controller={controller} />
        </div>
    </div>

    <div id="game-footer" class="flex flex-shrink-0 flex-grow-0 justify-center items-center py-2">
        <button class="invisible mr-auto ml-16">Submit</button>
        <button id="mark-button" class="mx-2" on:click={() => controller.selectionMode = SelectionMode.Marking} class:active={controller.selectionMode === SelectionMode.Marking}><div></div></button>
        <button id="cross-button" class="mx-2" on:click={() => controller.selectionMode = SelectionMode.Crossing} class:active={controller.selectionMode === SelectionMode.Crossing}></button>
        <button on:click={submitSolution} class="ml-auto mr-16">Submit</button>
    </div>
</div>

<style>
    #game-header, #game-footer {
        height: 10vh;
    }
</style>
// NonoGrid.svelte
<div id="grid-container">
    <div id="column-headings">
        {#each $gridStore as column}
            <span>
                {#each GridHelper.getColGroups(column[0].x) as groupNum}
                {groupNum}<br>
                {/each}
            </span>
        {/each}
    </div>
    <div id="row-headings">
        {#each $gridStore[0] as rowCell}
            <div>
            <span>
                {#each GridHelper.getRowGroups(rowCell.y) as groupNum}
                {groupNum}&nbsp;
                {/each}
            </span>
            </div>
        {/each}
    </div>

    <div id="cell-container" 
    on:mousedown={dragSelector.onMouseDown}
    on:touchstart={dragSelector.onTouchStart}
    >
        {#each $gridStore as column}
        <div class="grid-column">
            {#each column as gridCell}
            <NonoCell gridCell={gridCell} />
            {/each}
        </div>
        {/each}
    </div>
</div>

<style lang="postcss">
    #grid-container {
        display: grid;
        grid-template-rows: fit-content(100px) 1fr;
        grid-template-columns: fit-content(150px) 1fr;
        grid-template-areas: "x col"
                             "row cells";
    }

    #column-headings, #row-headings {
        @apply text-xl sm:text-3xl md:text-4xl;
    }

    #column-headings {
        grid-area: col;
        display: flex;
        align-items: flex-end;
    }
    #column-headings > span {
        width: 100%;
        text-align: center;
    }

    #row-headings {
        grid-area: row;
        display: flex;
        flex-direction: column-reverse;
    }

    #row-headings > div {
        height: 100%;
        vertical-align: middle;
        text-align: right;
        display: flex;
        justify-content: flex-end;
        align-items: center;
    }

    #cell-container {
        grid-area: cells;
        display: flex;
        flex-direction: row;
    }

    .grid-column {
        display: flex;
        flex-direction: column-reverse;
        width: 100%;
    }
</style>

如有必要,我可以使用 Svelte 添加一些动态 CSS 样式来响应我正在渲染的网格的大小,如下所示:

#cell-container {
  grid-template-rows: var(--template-rows);
  grid-template-columns: var(--template-columns);
}

但我真的不想让 Svelte 负责响应屏幕尺寸。这就是 Grid 和 Flexbox 的用途。

我尝试像这样重构我的网格:

<div id="cell-container" 
    on:mousedown={dragSelector.onMouseDown}
    on:touchstart={dragSelector.onTouchStart}
    >
        {#each $gridStore as column}
            {#each column.reverse() as gridCell}
            <NonoCell gridCell={gridCell} />
            {/each}
        {/each}
    </div>
...
<style>
...
/* Static for 5x5 grid; can be dynamic with a css var if it worked in the first place */
#cell-container {
        grid-area: cells;
        display: grid;
        grid-auto-flow: column;
        grid-template-rows: repeat(5, 1fr);
        grid-template-columns: repeat(5, 1fr);
}
...
</style>

但这对这种情况并没有多大帮助;事实上,当我放大和缩小它时,会发生更多奇怪的行为。

我创建了一个带有简化代码和 5x5 网格的 CodePen,供任何人测试。对不起,如果它不是完全整洁和格式化;我尽力了。 https://codepen.io/brooksvb/pen/eYReGRR

提前感谢您的帮助。一个多星期以来,我一直在与这个问题作斗争。

加分项:我想添加的一个功能,但现在可以接受这个项目没有的功能,就是在 5 行/列的组之间出现一个小间隙,如下图所示。我已经对如何具有可变网格间隙进行了一些研究,但发现 Grid 目前除了网格范围的间隙值之外无法定义任何东西。如果您知道如何在您的解决方案中实现这一点,我很乐意看到任何东西。

【问题讨论】:

  • 您的 HTMl 中有两个 id="game-container",让我们用 id="game-container2" 来解决第二个问题。 ,然后添加一个 max-width ,max-width:70vh似乎很公平。最终网格和对齐项目放在中间。 : 用你的笔来证明这个想法codepen.io/gc-nomade/pen/yLXPper
  • 对重复的 id 表示遗憾。这并没有促成这个问题;当我尝试准备要共享的 codepen 并将其固定在原始 codepen 上时添加了它。如果网格的宽度大于高度,您的修复会浪费大量垂直空间:codepen.io/brooksvb/pen/jOwaYzj 如果网格大于宽度,则网格会完全炸毁:codepen.io/brooksvb/pen/vYZWpbj
  • class="text-xl sm:text-3xl md:text-4xl" 适用于小网格,但在第二个示例中太大而无法适应屏幕。我建议,从你的笔,将 grid-container2 保留在视图内,以避免它溢出页脚。一个选项是允许窗口滚动并且网格将页脚向下推。 ;) 或者随着它变大而缩小每件东西的大小,在某一时刻,你必须让它溢出,这样它才能保持可读性。一点 js 可以帮助管理网格单元的大小? codepen.io/gc-nomade/pen/GREOBjo 和字体大小的夹子? (它唯一的 cmets )
  • 谢谢,我得深入研究一下并进行试验。我不知道 CSS 计数器是一回事
  • 感谢您花时间创建此建议。我确实从您处理问题的方式中学到了一些想法,尽管我最终编写了一些 Javascript 来调整单元格的大小。稍后我可能会重新审视这个问题,并以与您的布局方式更相似的不同方式来解决问题。 :)

标签: css layout flexbox css-grid


【解决方案1】:

我想把我使用的解决方案留在这里;我写了一些 Javascript 来计算单元格大小。 G-Cyrillus 上面的评论也很好地了解了如何重组网格以处理它,我可能会重新访问。

// NonoGrid.svelte
<script>
...
// DOM Elements
let gridSlot;
let columnHeadings;
let rowHeadings;
let gridColumns = [];

// This function calculates the size of cells based on screen space
const resizeCells = () => {
    // Max height and width available
    let maxHeight = gridSlot.clientHeight;
    let maxWidth = gridSlot.clientWidth;

    // Get height and width occupied by headers
    let colHeaderHeight = columnHeadings.clientHeight;
    let rowHeaderWidth = rowHeadings.clientWidth;

    // Divide remaining space among rows and cols
    let availableHeight = (maxHeight - colHeaderHeight) / controller.getRows();
    let availableWidth = (maxWidth - rowHeaderWidth) / controller.getCols();

    // Choose smallest for both dimensions to make square
    let targetCellSize = (availableHeight < availableWidth ? availableHeight : availableWidth) + 'px';

    // console.log(`Resizing to target: ${targetCellSize}`);

    gridColumns.forEach((colElem) => {
        colElem.style.width = targetCellSize;
    });
}

onMount(() => resizeCells());
</script>

<svelte:window on:resize={resizeCells}></svelte:window>

<!-- Add grid slot to set max-height and contain the container, centered inside. Also add DOM bindings for above access -->
<div id="grid-slot" class="flex" bind:this={gridSlot}>
    <div id="grid-container">
        <div id="column-headings" bind:this={columnHeadings}>
            ...
        </div>
        <div id="row-headings" bind:this={rowHeadings}>
            ...
        </div>

        <div id="cell-container" 
        on:mousedown={dragSelector.onMouseDown}
        on:touchstart={dragSelector.onTouchStart}
        >
            {#each $gridStore as column, i}
            <div class="grid-column" bind:this={gridColumns[i]}>
                {#each column as gridCell}
                <NonoCell gridCell={gridCell} />
                {/each}
            </div>
            {/each}
        </div>
    </div>
</div>


<style lang="postcss">
    #grid-slot {
        height: 80vh; // Set the height limit
    }

    #grid-container {
        width: min-content; // Needed to scale down the column headers when columns shrink
        margin: auto; // Centers horizontally and vertically (thanks to flex container)
        ...
    }
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-21
    • 2015-03-21
    • 2013-08-10
    • 1970-01-01
    • 2018-01-05
    • 2012-11-06
    • 1970-01-01
    • 2014-08-31
    相关资源
    最近更新 更多