Гибкая двухмерная компоновка: перенос строк совместно с сокращением столбцовCSS

Разбираемся в CSS
Ответить
Anonymous
 Гибкая двухмерная компоновка: перенос строк совместно с сокращением столбцов

Сообщение Anonymous »

в первом фрагменте кода ниже я показываю макет с использованием flex-flow: row Wrap, который имеет желаемые свойства макета, но может превышать максимальную заданную высоту контейнера. Во втором фрагменте кода показан макет с flex-flow:column nowrap, который обеспечивает желаемое поведение, сохраняя общую высоту содержимого на одном экране, но для одного столбца.
Мне нужен макет, сочетающий в себе желаемые свойства обоих, в частности, я хотел бы достичь следующих целей:
  • все элементы внутри контейнера будут иметь одинаковая ширина: 30 пикселей или 20 пикселей, в зависимости от того, что меньше. Когда элементов больше, чем помещается в одной строке, они переносятся в новую строку.
  • Все элементы имеют (квантованную и статически заданную) произвольную высоту, строки должны быть достаточно высокими для их самых высоких элемент и не обязательно будет иметь одинаковую высоту.
  • если конечный результат имеет высоту, превышающую некоторый максимум, например 90vh, он должен сжать все строки в одинаковой пропорции, чтобы они поместились на указанную максимальную высоту. (как будто у них было свойство flex-shrink: 1 в вертикальном направлении)
Лично я не приму ответ, в котором для установки стиля используется Javascript, но вы можете опубликовать его, чтобы помочь людям с похожими проблемами, но с менее строгими требованиями. Я бы предпочел решение на чистом CSS, которое было бы достаточно близко, чем решение, которое работает идеально, если вы настроите все правильные прослушиватели.
Мой текущий макет
Ниже приведен макет, который я использую в настоящее время: есть #gameContainer, который содержит список .Tube, каждый из которых содержит несколько .Ball. Переменная --ball-size устанавливается в корневом контейнере, чтобы сделать ширину всех трубок одинаковой. Каждая трубка имеет свойство --capacity, позволяющее указать ее высоту, кратную --ball- size.
Если вы измените ширину основного контейнера и/или размер шара, вы увидите, что если он превысит указанную максимальную высоту: 90vh в основном контейнере он переполняется, перекрываясь содержимым нижнего колонтитула (установка ширины 140 помогает мне, но может отличаться, если ваше окно просмотра имеет другой размер)

Код: Выделить всё

/**
* sets a style property of the #gameContainer
* the property set is the `name` field of the given input
* and the value is the value from the input with the specified suffix.
*/
function updateGameContainerStyle(inputForm, suffix=""){
document.getElementById("gameContainer").style.setProperty(inputForm.name, inputForm.value + suffix);
}

Код: Выделить всё

#gameContainer {
/* size of each ball, represents the size for clickable elements */
--ball-size: 30px;
width: 210px;
/* make the boundary of the container easier to identify */
border: 2px solid red;
/* desirable to have the game not take more than majority of height of screen */
max-height: 90vh;
/* plesent spacing between tubes */
display: flex;
flex-flow: row wrap;
gap: 5px;
justify-content: space-evenly;
/* when tubes of different heights are on same row align to the bottom */
align-items: flex-end;
}
.Tube {
display: flex;
/* order contents from bottom up */
flex-flow: column-reverse nowrap;
/* tube is one ball wide and `capacity` balls high */
width: var(--ball-size);
height: calc(var(--ball-size) * var(--capacity));
/* if the container size is small enough shrink elements to be a fifth or so of the container,
because of gaps and borders this generally means there will never be less than 3-4 tubes per row */
max-width: 20%;
/* to show border of tubes */
border: 3px solid blue;
}
.Ball {
/* since the hight of of tube is ball-size*capacity this ends up
being just ball-size, but is dynamic so if tube had to
be shrunk it stills is the right proportion */
flex-basis: calc(100%/var(--capacity));
align-content: center;
text-align: center;
}
.Ball.A {
background-color: rgba(255,0,0,0.5);
}
.Ball.B {
background-color: rgba(0,0,255,0.5);
}
.Ball.C {
background-color: rgba(0,255,0,0.5);
}

Код: Выделить всё


--ball-size = px

width = px




 A
B
A


 A
B
C
C


 B
B


 C
A


 C



this is footer content



Я хотел бы эффективно указать .Tube height как flex-basis в направлении столбца, а также flex-shrink: 1, это означает, что оно сожмет содержимое, чтобы оно соответствовало моей максимально допустимой высоте. Однако очевидно, что это невозможно одновременно с использованием flex-flow: перенос строк.
пример с одним столбцом
Для демонстрации мое желательное поведение. Я включил почти идентичную копию приведенного выше фрагмента, только с измененными свойствами .Tube {height} и #gameContainer {flex-flow} и меньшим количеством трубок, чтобы сделать его более разумным. видеть. Если вы измените размер шара, вы увидите, что при более низких значениях размер всей доски является переменным, но при определенном размере он перестает становиться выше, поэтому весь контейнер по-прежнему умещается в пределах 90vh, а нижний колонтитул никогда не перекрывается.< /p>
(также обратите внимание, что максимальная ширина: 20% здесь все еще действует, поэтому трубы не станут шире, чем пятая часть контейнера)

Код: Выделить всё

function updateGameContainerStyle2(inputForm, suffix=""){
document.getElementById("gameContainer2").style.setProperty(inputForm.name, inputForm.value + suffix);
}

Код: Выделить всё

#gameContainer2 {
/* size of each ball, represents the size for clickable elements */
--ball-size: 30px;
width: 210px;
/* make the boundary of the container easier to identify */
border: 2px solid red;
/* desirable to have the game not take more than majority of height of screen */
max-height: 90vh;
/* plesent spacing between tubes */
display: flex;
flex-flow: column nowrap;
gap: 5px;
justify-content: space-evenly;
/* when tubes of different heights are on same row align to the bottom */
align-items: flex-end;
}
.Tube {
display: flex;
/* order contents from bottom up */
flex-flow: column-reverse nowrap;
/* tube is one ball wide and `capacity` balls high */
width: var(--ball-size);
flex-basis: calc(var(--ball-size) * var(--capacity));
flex-shrink: 1;
/* if the container size is small enough don't shrink elements to be thinner than a fifth or so of the container
because of gaps and borders this generally means there will never be less than 3-4 tubes per row */
max-width: 20%;
/* to show border of tubes */
border: 3px solid blue;
}
.Ball {
/* since the hight of of tube is ball-size*capacity this ends up being just ball-size, but is dynamic so if tube had to be shrunk it stills is the right proportion */
flex-basis: calc(100%/var(--capacity));
align-content: center;
text-align: center;
}
.Ball.A {
background-color: rgba(255,0,0,0.5);
}
.Ball.B {
background-color: rgba(0,0,255,0.5);
}
.Ball.C {
background-color: rgba(0,255,0,0.5);
}

Код: Выделить всё


--ball-size = px

width = px




 A
B
C


 A
B


 B
C



this is footer content



Есть ли способ одновременного переноса строк, например поведение и поведение сжатия в направлении столбца? Я подозреваю, что может быть решение с использованием сетки, но самое близкое, что я смог получить, это использовать:

Код: Выделить всё

#gameContainer {
display: grid;
grid-template-columns: repeat(auto-fill, clamp(1ch, var(--ball-size), 20vw));
}
который ведет в основном то же самое поведение, что и первая версия, он создает автоматическое количество столбцов, которые используют переменную ball-size в качестве ширины, но ограничиваются так, чтобы их ширина не превышала чем 20vw (и шириной не менее 1 символа). Однако мне неизвестна какая-либо эквивалентная функция гибкого сжатия с использованием отображения сетки.


Подробнее здесь: https://stackoverflow.com/questions/790 ... umn-shrink
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «CSS»