CSS: как предотвратить пустые ячейки в сетке (удалив частично пустые строки) - PullRequest
0 голосов
/ 06 ноября 2019

Я пытаюсь создать сетку элементов div, ширина каждого пикселя которых должна составлять X пикселей, и столько строк, сколько необходимо для их размещения. Я не знаю ширину внешнего div. Это легко сделать с помощью сетки CSS:

#container {
  resize: both;
  overflow: auto;
  width: 170px;

  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));
  
}

#container div {
  border: 1px solid red;
}
<div id="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>

Теперь моя проблема в том, что я не хочу, чтобы в моей сетке были пустые ячейки (по эстетическим соображениям). Поэтому я хочу спрятать все элементы в последнем ряду, как показано здесь:

Example image

Обратите внимание, что наличие сетки, умещающейся в 3 столбца, является просто особым случаемпроблемы: если я могу разместить 5 столбцов в сетке, я хочу удалить все элементы во второй строке.

Возможно ли добиться этого в CSS? В идеале без добавления вручнуюмедиа-точки останова и скрытие элементов в css вручную?

Если нет, то можно ли решить эту проблему с помощью Javascript?

Обратите внимание, что хотя я использовал css display:grid в моем примере, это не требуется - все, что я хочу, это то, что выглядиткак сетка.

Ответы [ 3 ]

0 голосов
/ 06 ноября 2019

Один хак - рассмотреть псевдоэлемент, который их скрывает. Конечно, у вас не будет прозрачности, и ваш элемент не будет соответствовать высоте контейнера.

#container {
  resize: both;
  overflow: hidden;
  width: 170px;

  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));
  
}

#container div {
  border: 1px solid red;
}

#container:after {
  content:"";
  background:#fff;
  margin-left:-100vw;
  margin-right:20px;
  
}
<div id="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>
0 голосов
/ 07 ноября 2019

Поскольку кажется, что это невозможно только с помощью CSS, в конце концов я решил решить эту проблему с помощью javascript, например:

var cg = document.getElementById('container');

var style = document.createElement('style');
document.head.appendChild(style);

var hideHalfEmptyColumns = function() {
  // How many columns it's gonna be
  var columns = Math.floor(cg.offsetWidth / 50);
  // How many elements are showing
  var elements = cg.childElementCount;
  // How many cells are on completely filled rows
  var elementsToShow = columns * Math.floor(elements / columns);
  style.innerHTML = `
            #container>div:nth-child(n + ${elementsToShow+1}) {
                display: none;
            }`;
}

// In the real world I'd run this on the window resize event as well, but since elements does not have this function the example is a bit broken
hideHalfEmptyColumns();
#container {
  resize: both;
  overflow: auto;
  width: 170px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));
}

#container div {
  border: 1px solid red;
}
<div id="container">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
</div>
0 голосов
/ 06 ноября 2019

Этого невозможно достичь, используя только CSS. Это может быть, если вы разделите строки в html следующим образом:

<div class="row">
    <div class="cell">1</div>
    <div class="cell">2</div>
    <div class="cell">3</div>
</div>
<div class="row">
    <div class="cell">4</div>
    <div class="cell">5</div>
    <div class="cell">6</div>
</div>
<div class="row">
    <div class="cell"></div>
    <div class="cell">7</div>
    <div class="cell">8</div>
</div>

И убедитесь, что первая ячейка в строке будет такой, что пустая Тогда вы можете написать CSS-селекторы, используя псевдоселектор :empty и общий родственный селектор~

.row {
  display: block;
}

.cell {
  display: inline-block;
  width: 70px;
  height: 25px;
  background: yellow;
}

.cell:empty,
.cell:empty ~ .cell {
  display: none;
}
<div class="row">
    <div class="cell">1</div>
    <div class="cell">2</div>
    <div class="cell">3</div>
</div>
<div class="row">
    <div class="cell">4</div>
    <div class="cell">5</div>
    <div class="cell">6</div>
</div>
<div class="row">
    <div class="cell"></div>
    <div class="cell">7</div>
    <div class="cell">8</div>
</div>

Другой способ - использовать javascript, который должен быть довольно тривиальным

const hideRowIfAnyCellEmpty = () => {
  const rows = document.querySelectorAll('.row');
  rows.forEach((row) => {
    if (hasRowEmptyCell(row)){
      row.classList.add('has-empty-cell');
    }
  });
}

const hasRowEmptyCell = (row) => {
  return row.querySelectorAll('.cell:empty').length;
};

hideRowIfAnyCellEmpty();
.row {
  display: block;
}

.row.has-empty-cell {
  display: none;
}

.cell {
  display: inline-block;
  width: 70px;
  height: 25px;
  background: yellow;
}
<div class="row">
    <div class="cell">1</div>
    <div class="cell">2</div>
    <div class="cell">3</div>
</div>
<div class="row">
    <div class="cell">4</div>
    <div class="cell">5</div>
    <div class="cell">6</div>
</div>
<div class="row">
    <div class="cell"></div>
    <div class="cell">7</div>
    <div class="cell">8</div>
</div>
...