Создайте игровой автомат с детьми динамической высоты

Я работаю над макетом, который по своей природе похож на игровой автомат. Каждый из его дочерних элементов будет текстом, а макет является адаптивным (поэтому при разных разрешениях дочерний текст может переноситься или не переноситься на несколько строк, изменяя таким образом высоту).

Макет будет иметь видимое «окно просмотра» 3 элементов одновременно. Чтобы «окно просмотра» не смещалось, все дочерние элементы должны иметь одинаковую высоту. Это заставило меня задуматься о двух разных маршрутах, но я не могу заставить их работать.

  1. Использовать отображение: flex. С макетом столбца вы можете сложить их все в стопку. Проблема в том, что я не думаю, что вы можете сделать все дочерние элементы одинаковой высоты, если вы не укажете расчетную высоту в контейнере flex (таким образом, вам придется использовать js для расчета максимальной высоты всех дочерних элементов flex )
  2. Используйте отображение: сетка. Из коробки вы можете сделать все дочерние элементы одинаковой высоты с сеткой. Проблема в том, как скрыть переполнение, гарантирующее, что вы показываете только 3 за раз в «окне просмотра» для игрового автомата?

Этот макет может быть невозможен без вычислений js, но из-за того, что он должен быть полностью отзывчивым, я не хочу повторять вычисления при каждом изменении размера окна. Может ли кто-нибудь придумать способ сделать это, используя чистый css?

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

var scroll = document.getElementById('scroll');
var wrapper = document.getElementById('wrapper');

scroll.addEventListener('click', function() {
  wrapper.classList.toggle('scrolled');
});
.example {
  display: flex;
}

.container {
  height: 90px;
  width: 300px;
  outline: 1px solid red;
  z-index:1;
}

.wrapper {
  display: flex;
  flex-direction: column;
  transition-property: transform;
  transition-duration: 500ms;
}

.wrapper.scrolled {
  transform: translateY(-300px);
}

.inner {
  outline: 1px solid blue;
  flex-grow: 1;
  height: 30px;
}

.buttons {
  margin-right: 3em;
}
<div class="example">
  <div class="buttons">
    <button id="scroll">Scroll</button>
  </div>

  <div class="container">
    <div id="wrapper" class="wrapper">
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
      <div class="inner">Some text</div>
    </div>
  </div>
</div>


person jas7457    schedule 17.11.2017    source источник
comment
Нельзя ли использовать проц для контейнера? Ширина лайка: 100%;   -  person GoofBall101    schedule 17.11.2017
comment
Как бы вы использовали процент для контейнера?   -  person jas7457    schedule 17.11.2017
comment
Вместо пикселей используйте проценты, так как это делает приложение более отзывчивым.   -  person GoofBall101    schedule 17.11.2017
comment
Установка высоты в процентах для .container ничего не даст. Это будет процент от роста его родителя. Его высота должна определяться тремя его дочерними элементами. Я не уверен, что вы читали мой вопрос или смотрели на мой пример...   -  person jas7457    schedule 17.11.2017
comment
Я только что перечитал его и думаю, что понял, о чем вы просите — моя идея в том, что вы могли бы установить для каждого из детей специальные идентификаторы. Когда вы нажимаете кнопку, она генерирует случайное число в пределах количества детей. С этим случайным числом найдите 2 рядом с одним дочерним элементом и с помощью Js сделайте так, чтобы дополнительные неиспользуемые дочерние элементы имели класс, который отображает: none;   -  person GoofBall101    schedule 17.11.2017
comment
При этом будет 0 анимации, она сразу же перейдет из начального состояния в конечное состояние без анимации прокрутки, как у меня. Кроме того, если бы все 3, которые были первоначально показаны, имели высоту в 1 строку, а следующие 3 были бы высотой в 2 строки, это по существу удвоило бы ограничивающий контейнер после этого изменения состояния. Так не пойдет.   -  person jas7457    schedule 17.11.2017
comment
Вы всегда можете сделать анимацию между нажатием кнопки и отображением конечного результата. Что касается двойной строки, я бы сделал ограничивающий контейнер уже размером с две строки. И если они занимают более 2 строк, просто не показывайте лишнее «думаю, есть ли имена», тогда, если используется только одна строка, другая может быть пустой.   -  person GoofBall101    schedule 17.11.2017
comment
Две линии были произвольными. Это может охватывать 4, 5, кто знает. Это не решение. Это не отвечает на мой первоначальный вопрос.   -  person jas7457    schedule 17.11.2017
comment
Необходима ли поддержка браузеров Microcrap?   -  person zer00ne    schedule 17.11.2017
comment
К сожалению, да. Приходится возвращаться к IE10. Что у тебя было на уме?   -  person jas7457    schedule 17.11.2017
comment
Я не хочу повторять расчеты при каждом изменении размера окна. Как часто, по вашему мнению, обычный пользователь меняет размер окна браузера? ... Пользователи могут наклонять свой планшет/телефон/ПК, поэтому вам нужна функция изменения размера, если вы хотите, чтобы он выглядел хорошо, так что вы все еще не хотите использовать событие изменения размера?   -  person Ason    schedule 17.11.2017
comment
Обычный пользователь не будет делать это слишком часто, я просто надеялся, что есть какая-то альтернатива CSS. Если я не могу найти способ сделать это на чистом CSS, я буду полагаться на изменение размера окна.   -  person jas7457    schedule 17.11.2017


Ответы (1)


Эй, я думаю, что понял, к чему вы здесь стремитесь, и разработал механику «игрового автомата», которая масштабирует свои внутренние и внешние объекты с помощью vh.

Таким образом, объект-контейнер будет иметь что-то вроде...

.container {
    width: 300px;
    height: 90vh;
    outline: 1px solid red;
    z-index:1;
    overflow: hidden;
}

... и внутренний объект будет иметь что-то вроде...

.inner {
    outline: 1px solid blue;
    flex-grow: 1;
    height: 30vh;
}

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

var scroll = document.getElementById('scroll');
var wrapper = document.getElementById('wrapper');
var innerArray = document.getElementsByClassName('inner');

var innerNum = 1; // Start at the second element
scroll.addEventListener('click', function() {
  if (innerNum == innerArray.length-2) { // Check to see if the last item has been scrolled to
    innerNum = 0; // Scroll back to the first item if it has
  }
  //wrapper.classList.toggle('scrolled');
  innerArray[innerNum].scrollIntoView({ 
    behavior: 'smooth' 
  });
  innerNum++;
});

Вот Codepen, демонстрирующий пример. Я могу уточнить код, если хотите. Мои извинения, если я был далеко от мяча на то, что вы собирались!

person Chase Ingebritson    schedule 17.11.2017
comment
Вы не ошиблись, и я понимаю, что вы сделали, однако это только маскирует основную проблему. 1. На экране куча других вещей, так что использовать vh не совсем вариант. 2. Что делать, если 30vh недостаточно высоки, когда кто-то делает это на мобильном телефоне в ландшафтном режиме? - person jas7457; 17.11.2017