【问题标题】:With CSS Grids, is there a way to wrap the implicit grid when using grid-auto-flow: column?使用 CSS 网格,在使用 grid-auto-flow: column 时有没有办法包装隐式网格?
【发布时间】:2017-12-04 20:58:19
【问题描述】:

我正在尝试实现一个 4x2 网格的布局,该网格(使用grid-auto-flow: column)流入下面的第二个 4x2 网格。本质上,我试图将一个 8x2 网格切成两半,然后将两半放在另一半上。有没有办法让这个布局自己环绕?

到目前为止,我的网格布局为

grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 1fr);

子节点分为3类:小、中、大

.c-small { }

.c-medium {
  grid-row: auto / span 2;
}

.c-large {
  grid-column: auto / span 2;
  grid-row: auto / span 2;
}

有没有办法让我将隐式网格包裹到底部而不是将其砸在网格的右侧?

如果没有 JS,我什至不确定我在尝试什么。 (现在我正在考虑一种解决方案,当它们溢出时,我手动将项目从一个网格移动到单独的第二个网格,但我不知道检查网格项目是否溢出到隐式网格中的方法。)

代码笔here

// VARS
var count = 0;

// HELPERS
function grab(id) {
  return document.getElementById(id);
}

// GRIDS
var grid1 = {
  spaceLeft: 8,
  add: function(size) {
    switch (size) {
      case 'S':
        this.addToBack(createEmptySmall())
        break;
      case 'M':
        this.addToBack(createEmptyMedium())
        break;
      case 'L':
        this.addToBack(createEmptyLarge())
        break;
      default:
    }
  },
  prep: function(elem) {
    // if (elem === undefined) { break; }

    switch (elem.getAttribute('size')) {
      case "S":
        this.spaceLeft -= 1;
        break;
      case "M":
        this.spaceLeft -= 2;
        break;
      case "L":
        this.spaceLeft -= 4;
        break;
      default:
    }
    
    return elem;
  },

  addToFront: function(elem) {
    elem = this.prep(elem);
    addToFront(grab('js-grid1'), elem);
  },

  addToBack: function(elem) {
    elem = this.prep(elem);
    addToBack(grab('js-grid1'), elem);
  },
}

var grid2 = {
  spaceLeft: 8,
  addToFront: function(elem) {
    if (elem === undefined) {
      elem = createEmptyMedium()
    }
    // switch (elem.getAttribute('size')) {
    //   case "S":
    //     this.spaceLeft -= 1;
    //     break;
    //   case "M":
    //     this.spaceLeft -= 2;
    //     break;
    //   case "L":
    //     this.spaceLeft -= 4;
    //     break;
    //   default:
    //
    // }
    addToFront(grab('js-grid2'), elem);
  }
}

//METHODS
function createEmptySmall() {
  var elem = document.createElement("div");
  elem.classList.add("a-grid__item", "c-small");
  elem.setAttribute('size', "S");
  count++;
  elem.innerHTML = count.toString();

  return elem;
}

function createEmptyMedium() {
  var elem = document.createElement("div");
  elem.classList.add("a-grid__item", "c-medium");
  elem.setAttribute('size', "M");
  count++;
  elem.innerHTML = count.toString();

  return elem;
}

function createEmptyLarge() {
  var elem = document.createElement("div");
  elem.classList.add("a-grid__item", "c-large");
  elem.setAttribute('size', "L");
  count++;
  elem.innerHTML = count.toString();

  return elem;
}

function addToFront(grid, elem) {
  grid.insertBefore(elem, grid.childNodes[0]);
}

function addToBack(grid, elem) {
  grid.appendChild(elem, grid.childNodes[0]);
}

function shift() {
  var elem = grab('js-grid1').lastElementChild;
  grid2.addToFront(elem);
}

function changeSize(elem, size) {
  console.log('hit');
  if (size === undefined) {
    switch (elem.getAttribute('size')) {
      case "S":
        size = "M"
        break;
      case "M":
        size = "L"
        break;
      case "L":
        size = "S"
        break;
      default:
        size = "M";
    }
  }

  if (size == "S" || size == "M" || size == "L") {
    elem.setAttribute('size', size);

    switch (elem.getAttribute('size')) {
      case "S":
        elem.className = "a-grid__item c-small"
        break;
      case "M":
        elem.className = "a-grid__item c-medium"
        break;
      case "L":
        elem.className = "a-grid__item c-large"
        break;
      default:

    }
  }
}
/* OVERRIDES */
body {
  font-family: sans-serif;
  margin: 0;
  min-height: inherit !important;
}

/* LAYOUTS */
.l-canvas {
  width: 100%;
  height: calc(100vh - 70px);
  background-color: rgba(0, 0, 0, 0.05);
}

.l-grid {
  height: calc(50vh - 70px - 32px);
  /* 100vh */
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 1fr);
  grid-column-gap: 16px;
  grid-row-gap: 16px;
  grid-auto-flow: column;
  padding: 16px;
}

.l-buttons {
  position: fixed;
  bottom: 0;
  right: 0;
  height: 56px;
  padding: 16px 16px;
}

/* ATOMS */
.a-grid__item {
  background-color: rgba(0, 0, 0, 0.2);
  /* height: 200px; */
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
}

/* COMPONENTS */
.c-title {
  font-size: 24px;
  font-weight: bold;
  line-height: 28px;
  padding-bottom: 8px;
  margin: 16px 8px;
  border-bottom: 2px solid #333;
}

.c-small {
  /* auto */
}

.c-medium {
  grid-row: auto / span 2;
}

.c-large {
  grid-column: auto / span 2;
  grid-row: auto / span 2;
}
<div class="c-title">
  CSS Grids
</div>
<div class="l-canvas">
  <div id="js-grid1" class="l-grid">
    <div class="a-grid__item c-small" onclick="changeSize(this)">
      1
    </div>
    <div class="a-grid__item c-small" onclick="changeSize(this)">
      2
    </div>
    <div class="a-grid__item c-medium" onclick="changeSize(this)">
      3
    </div>
    <div class="a-grid__item c-small" onclick="changeSize(this)">
      4
    </div>
    <div class="a-grid__item c-medium" onclick="changeSize(this)">
      5
    </div>
  </div>
  <div id="js-grid2" class="l-grid">
    <div class="a-grid__item c-small" onclick="changeSize(this)">
      6
    </div>
    <div class="a-grid__item c-large" onclick="changeSize(this)">
      7
    </div>
    <div class="a-grid__item c-medium" onclick="changeSize(this)">
      8
    </div>
  </div>
</div>

【问题讨论】:

  • Codepen added
  • 我有点不清楚你到底想要完成什么。您是否尝试将 #js-grid1#js-grid2 合并为一个元素,但保留图片/codepen 中的布局?
  • 是的。我正在尝试实现动态布局,其中从顶部溢出的网格项目被移动到底部。我已经尽可能接近两个单独的网格,但这里的问题是我必须手动将网格项目从一个网格转移到另一个网格,我不知道是否有办法知道一个网格项目是否溢出。
  • 所以将所有项目组合到一个网格容器中不是一种选择?
  • 这个想法是让它跨越两行。如果我有办法做到这一点并将所有内容都放在一个网格容器中,那就太完美了!

标签: javascript css grid-layout css-grid


【解决方案1】:

首先,您需要从网格中隐藏所有溢出元素。为此,我更改了网格的样式。

.l-grid {
  height: calc(50vh - 70px - 32px);
  display: grid;
  /* fixed percentage minus (n-1)/n * column gap, n is column count */
  /* with calc to include gaps instead of flexible fr units */
  grid-template-columns: repeat(4, calc(25% - 12px));
  grid-template-rows: repeat(2, 1fr);
  /* set auto generated column width to 0 */ 
  grid-auto-columns: 0;
  /* hide when overflow */
  overflow: hidden;
  grid-gap: 16px;
  grid-auto-flow: column;
  margin: 16px;
}

在 JavaScript 中,我添加了函数 changeSize 以根据 CSS 类更改大小。

然后我添加了函数isHidden来计算网格项是否基于右侧坐标隐藏(因为溢出时可以裁剪两列项)。

最后moveHiddenElementsToNextGrid 函数恢复原始布局并将不可见项移动到第二个网格。

$(".a-grid__item").click(function() {
  var $gridItem = $(this);
  changeSize($gridItem);
  moveHiddenElementsToNextGrid();
});

function changeSize($gridItem) {
  if ($gridItem.hasClass("c-small")) {
    $gridItem.removeClass("c-small");
    $gridItem.addClass("c-medium");
  } else if ($gridItem.hasClass("c-medium")) {
    $gridItem.removeClass("c-medium");
    $gridItem.addClass("c-large");
  } else if ($gridItem.hasClass("c-large")) {
    $gridItem.removeClass("c-large");
    $gridItem.addClass("c-small");
  }
}

function isHidden($gridItem) {
    var elementRight = $gridItem.position().left + $gridItem.width();
    var parentWidth = $gridItem.parent().width();
    var parentMarginRight = parseInt($gridItem.parent().css("margin-right"));
    return elementRight - parentWidth > parentMarginRight;
};

function moveHiddenElementsToNextGrid() {
  $(".a-grid__item").appendTo("#js-grid1");
  $(".a-grid__item").filter(function() { return isHidden($(this)); }).appendTo("#js-grid2");
}

moveHiddenElementsToNextGrid();
/* OVERRIDES */

body {
  font-family: sans-serif;
  margin: 0;
}


/* LAYOUTS */

.l-canvas {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: calc(100vh - 70px);
  background-color: rgba(0, 0, 0, 0.05);
}

.l-grid {
  height: calc(50vh - 70px - 32px);
  /* 100vh */
  display: grid;
  grid-template-columns: repeat(4, calc(25% - 12px));
  grid-template-rows: repeat(2, 1fr);
  grid-auto-columns: 0;
  overflow: hidden;
  grid-gap: 16px;
  grid-auto-flow: column;
  margin: 16px;
}

.l-buttons {
  position: fixed;
  bottom: 0;
  right: 0;
  height: 56px;
  padding: 16px 16px;
}


/* ATOMS */

.a-grid__item {
  background-color: rgba(0, 0, 0, 0.2);
  /* height: 200px; */
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  min-width: 0;
}


/* COMPONENTS */

.c-title {
  font-size: 24px;
  font-weight: bold;
  line-height: 28px;
  padding-bottom: 8px;
  margin: 16px 8px;
  border-bottom: 2px solid #333;
}

.c-small {
  /* auto */
}

.c-medium {
  grid-row: auto / span 2;
}

.c-large {
  grid-column: auto / span 2;
  grid-row: auto / span 2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="c-title">
  CSS Grids
</div>
<div class="l-canvas">
  <div id="js-grid1" class="l-grid">
    <div class="a-grid__item c-small">
      1
    </div>
    <div class="a-grid__item c-small">
      2
    </div>
    <div class="a-grid__item c-medium">
      3
    </div>
    <div class="a-grid__item c-small">
      4
    </div>
    <div class="a-grid__item c-medium">
      5
    </div>
    <div class="a-grid__item c-small">
      6
    </div>
    <div class="a-grid__item c-large">
      7
    </div>
    <div class="a-grid__item c-medium">
      8
    </div>
  </div>
  <div id="js-grid2" class="l-grid">
  </div>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    • 2011-04-18
    • 1970-01-01
    • 2019-02-21
    • 2020-04-23
    • 2017-06-05
    • 2022-01-17
    相关资源
    最近更新 更多