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

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

Сообщение Anonymous »

в первом фрагменте кода ниже я показываю макет с использованием flex-flow: row Wrap, который имеет желаемые свойства макета, но может превышать максимальную заданную высоту контейнера. Второй фрагмент кода показывает макет с flex-flow:column nowrap, который обеспечивает желаемое поведение, сохраняя общую высоту содержимого на одном экране, но для одного столбца.
Мне нужен макет, сочетающий в себе желаемые свойства обоих, в частности, я хотел бы достичь следующих целей:
  • все элементы внутри контейнера будут иметь одинаковая ширина: 30 пикселей или 20 пикселей, в зависимости от того, что меньше. Когда элементов больше, чем умещается в одной строке, они переносятся в новую строку. Очень часто их бывает больше, чем одна строка, поскольку обычно у меня от 7 до 16 трубок.
  • все элементы имеют произвольную высоту (квантованную и статически заданную), строки должны быть достаточно высокими для самого высокого элемента и не обязательно будут одинаковой высоты.
  • если конечный результат (обычно весь контейнер несколько строк) имеет высоту, превышающую некоторый максимум, например 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



Если бы я изменил структуру HTML, чтобы она имела промежуточный Я мог бы превратить игровую доску в столбец nowrap, а строки - в flex-shrink:1; flex-flow: row nowrap, который будет соответствовать критериям размера, но не будет перераспределять элементы между строками при изменении размера контейнера.
Есть ли способ обеспечить перенос строк< /code> подобное поведение и поведение сжатия в направлении столбца? Я подозреваю, что может быть решение с использованием сетки, но самое близкое, что я смог получить, это использовать:

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

#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»