Сделать столбец во всю ширину, если родственный столбец не существует

#css #css-grid

#css #css-сетка

Вопрос:

Я пытаюсь обеспечить несколько динамичное поведение в CSS-сетке, при этом базовые правила сетки должны быть статичными.

Я создал изолированную среду, чтобы лучше проиллюстрировать, что я хочу, чтобы произошло. Когда ЗЕЛЕНОЕ поле удаляется из DOM, я хочу, чтобы КРАСНОЕ покрывало всю первую строку, а когда будет видно ЗЕЛЕНОЕ, я хочу, чтобы у RED / GREEN было распределение 2fr / 1fr в первой строке.

Я просмотрел документы, чтобы попытаться найти способ сделать это, но единственное решение, которое я нахожу, связано с манипулированием CSS во «время выполнения». Возможно ли достичь этого только с помощью CSS?

 const toggleBtn = document.querySelector("button.toggle-green");
const grid = document.querySelector(".grid");
const yellow = document.querySelector(".yellow");

const getGreen = () => document.querySelector(".green");
const createGreen = () => {
  const div = document.createElement("div");
  div.className = "green";
  div.innerText = "GREEN";
  return div;
};

toggleBtn.addEventListener("click", () => {
  const green = getGreen();
  if (!green) {
    grid.insertBefore(createGreen(), yellow);
  } else {
    green.remove();
  }
});  
 body {
  font-family: sans-serif;
}

.grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-gap: 2px 2px;
}

.yellow {
  background: yellow;
  grid-column: span 2;
}

.red {
  background: red;
}

.green {
  background: green;
}  
 <div class="grid">
  <div class="red">RED</div>
  <div class="green">GREEN</div>
  <div class="yellow">YELLOW</div>
</div>
<button class="toggle-green">Toggle green</button>  

Комментарии:

1. Честно говоря, это звучит так, как будто flexbox мог бы это исправить,

Ответ №1:

Вы можете заставить его работать с CSS-сетками, но вам нужно тщательно настроить ширину, чтобы настроить его:

  • Создайте обтекающую сетку, используя grid-template-columns: repeat(auto-fit, minmax(66.66vw, 1fr)) — обратите внимание, что минимальная ширина здесь указана в единицах отображения.
  • Теперь установите min-width: 33.33vw значение для зеленой секции.

В приведенном ниже коде — обратите внимание на использование calc — это настраивает горизонтально для grid-gap . Смотрите демонстрацию ниже:

 const toggleBtn = document.querySelector("button.toggle-green");
const grid = document.querySelector(".grid");
const yellow = document.querySelector(".yellow");

const getGreen = () => document.querySelector(".green");
const createGreen = () => {
  const div = document.createElement("div");
  div.className = "green";
  div.innerText = "GREEN";
  return div;
};

toggleBtn.addEventListener("click", () => {
  const green = getGreen();
  if (!green) {
    grid.insertBefore(createGreen(), yellow);
  } else {
    green.remove();
  }
});  
 body {
  font-family: sans-serif;
  margin: 0;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(calc(66.66vw - 2px), 1fr));
  grid-gap: 2px 2px;
  width: 100vw;
}

.yellow {
  background: yellow;
  grid-column: span 2;
}

.red {
  background: red;
}

.green {
  background: green;
  min-width: 33.33vw;
}  
 <div class="grid">
  <div class="red">RED</div>
  <div class="green">GREEN</div>
  <div class="yellow">YELLOW</div>
</div>

<button class="toggle-green">Toggle green</button>  


Решение Flexbox

Но я бы предложил подход flexbox, с которым вы, должно быть, уже знакомы — используйте обтекающий flexbox и установите: — flex: 1 в зеленый раздел, — flex-basis: 100% в желтый раздел и — flex: 2 в красный раздел.

Смотрите демонстрацию ниже:

 const toggleBtn = document.querySelector("button.toggle-green");
const grid = document.querySelector(".grid");
const yellow = document.querySelector(".yellow");

const getGreen = () => document.querySelector(".green");
const createGreen = () => {
  const div = document.createElement("div");
  div.className = "green";
  div.innerText = "GREEN";
  return div;
};

toggleBtn.addEventListener("click", () => {
  const green = getGreen();
  if (!green) {
    grid.insertBefore(createGreen(), yellow);
  } else {
    green.remove();
  }
});  
 body {
  font-family: sans-serif;
  margin: 0;
}

.grid {
  display: flex;
  flex-wrap: wrap;
  width: 100vw;
}

.yellow {
  background: yellow;
  flex-basis: 100%;
}

.red {
  background: red;
  flex: 2;
}

.green {
  background: green;
  flex: 1;
}  
 <div class="grid">
  <div class="red">RED</div>
  <div class="green">GREEN</div>
  <div class="yellow">YELLOW</div>
</div>

<button class="toggle-green">Toggle green</button>