首页 > 解决方案 > 使用 grid-row-end 时网格子交换位置

问题描述

我正在为卡片列表开发网格布局。网格的预期结果显示在此图像中:

网格 - 预期结果

我期待卡片#1-6 从左到右和从上到下显示。在超过 6 张卡片的情况下,后续每批 6 张卡片(#7-12、#13-18、...)将遵循上图所示的相同网格布局模式,并将显示在下方上一批。

但是,在此问题底部发布的代码片段中,当视口宽度1200px大于或等于时,卡 #5 和 #6 交换列。在此断点处,#5 卡显示在#3 列中,#6 卡显示在#2 列中。我正在使用grid-row-end我的网格孩子来实现砖石外观,我认为这是问题所在:

.thumbnail:nth-child(2n + 1) {
    grid-row-end: span 5;
}

.thumbnail:nth-child(2n) {
    grid-row-end: span 6;
}

我不想手动设置每第 5 个和第 6 个孩子交换列,因为呈现的卡片数量是动态的:

// I do not want to declare these styles.
.thumbnail:nth-child(5) {
    grid-column: 2;
}

.thumbnail:nth-child(6) {
    grid-row: 6 / 12;
    grid-column: 3;
}

问题


const thumbnails = [
    { category: "Card 1", title: "Some title" },
    { category: "Card 2", title: "Some title" },
    { category: "Card 3", title: "Some title" },
    { category: "Card 4", title: "Some title" },
    { category: "Card 5", title: "Some title" },
    { category: "Card 6", title: "Some title" }
];

const Thumbnail = ({ category, title }) => (
    <li className="thumbnail">
        <div className="thumbnail__image-container"></div>
        <div className="thumbnail__metadata-container">
            <p>{category}</p>
            <h2>{title}</h2>
        </div>
    </li>
);

const Gallery = () => (
    <ul className="gallery">
        {thumbnails.map((thumbnail, i) => {
            return <Thumbnail key={thumbnail.category} {...thumbnail} />;
        })}
    </ul>
);

ReactDOM.render(<Gallery />, document.getElementById("app"));
* {
    margin: 0;
    padding: 0;
}

html {
    font-family: sans-serif;
}

.gallery {
    display: grid;
    grid-template-columns: repeat(1, 1fr);
    grid-gap: 14px;
    padding: 16px;
    list-style: none;
}

.thumbnail {
    display: flex;
    flex-direction: column;
}

.thumbnail__image-container {
    width: 100%;
    min-height: 200px;
    flex: 1;
    background: url("https://via.placeholder.com/150");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 125% auto;
}

.thumbnail__metadata-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 36px;
    text-align: center;
    background-color: lightblue;
}

@media (min-width: 768px) {
    .gallery {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 1200px) {
    .gallery {
        grid-template-columns: repeat(3, 1fr);
        grid-auto-rows: 60px;
        height: auto;
    }

    .thumbnail:nth-child(2n + 1) {
        grid-row-end: span 5;
    }

    .thumbnail:nth-child(2n) {
        grid-row-end: span 6;
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

标签: csscss-grid

解决方案


明确定义元素#5 的列并添加grid-auto-flow: dense;到网格中以确保元素#6 将正确放置。这也适用于任意数量的元素,因为您的模式是相同的并且每 6 个元素重复:

@media (min-width: 1200px) {
    .thumbnail:nth-child(6n + 5) {
        grid-column: 2;
    }
}

完整代码:

const thumbnails = [
    { category: "Card 1", title: "Some title" },
    { category: "Card 2", title: "Some title" },
    { category: "Card 3", title: "Some title" },
    { category: "Card 4", title: "Some title" },
    { category: "Card 5", title: "Some title" },
    { category: "Card 6", title: "Some title" },
    { category: "Card 7", title: "Some title" },
    { category: "Card 8", title: "Some title" },
    { category: "Card 9", title: "Some title" },
    { category: "Card 10", title: "Some title" },
    { category: "Card 11", title: "Some title" },
    { category: "Card 12", title: "Some title" }
];

const Thumbnail = ({ category, title }) => (
    <li className="thumbnail">
        <div className="thumbnail__image-container"></div>
        <div className="thumbnail__metadata-container">
            <p>{category}</p>
            <h2>{title}</h2>
        </div>
    </li>
);

const Gallery = () => (
    <ul className="gallery">
        {thumbnails.map((thumbnail, i) => {
            return <Thumbnail key={thumbnail.category} {...thumbnail} />;
        })}
    </ul>
);

ReactDOM.render(<Gallery />, document.getElementById("app"));
* {
    margin: 0;
    padding: 0;
}

html {
    font-family: sans-serif;
}

.gallery {
    display: grid;
    grid-template-columns: repeat(1, 1fr);
    grid-auto-flow:dense;
    grid-gap: 14px;
    padding: 16px;
    list-style: none;
}

.thumbnail {
    display: flex;
    flex-direction: column;
}

.thumbnail__image-container {
    width: 100%;
    min-height: 200px;
    flex: 1;
    background: url("https://via.placeholder.com/150");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 125% auto;
}

.thumbnail__metadata-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 36px;
    text-align: center;
    background-color: lightblue;
}

@media (min-width: 768px) {
    .gallery {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 1200px) {
    .gallery {
        grid-template-columns: repeat(3, 1fr);
        grid-auto-rows: 60px;
        height: auto;
    }

    .thumbnail:nth-child(2n + 1) {
        grid-row-end: span 5;
    }

    .thumbnail:nth-child(2n) {
        grid-row-end: span 6;
    }
    .thumbnail:nth-child(6n + 5) {
        grid-column: 2;
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>


推荐阅读