Правила компоновки
Этот раздел объясняет методы позиционирования визуальных компонентов и контейнеров в экранах.
Размеры компонентов
Компоненты, реализующие com.vaadin.flow.component.HasSize (например, button, textField, dataGrid, vbox, etc.) имеют следующие общие атрибуты: width, minWidth, maxWidth, height, minHeight, maxHeight. Эти атрибуты прямо соответствуют соответствующим по имени свойствам CSS.
| Атрибуты min/max размеров помогают в создании адаптивного дизайна, когда компоненты должны приспосабливаться к разным размерам экрана. Эти атрибуты также могут использоваться для предотвращения переполнения компонентов или их слишком большого размера. См. практический пример ниже. |
Размеры компонентов могут быть следующих типов:
-
Основанные на содержимом -
AUTO -
Фиксированные, например,
25em -
Относительные (в процентах) к родительскому контейнеру, например,
100%
| Значение размера должно быть корректной для CSS строкой размера. |
Размер, основанный на содержимом
Компонент займет достаточно места, чтобы вместить свое содержимое.
Примеры:
-
Для
buttonразмер определяется длиной значения атрибутаtext. -
Для контейнеров (layouts) размер определяется суммой всех размеров компонентов внутри контейнера.
<button text="Button" width="AUTO"/>
button.setWidth("AUTO");
Компоненты с размером, основанным на содержимом, будут автоматически изменять свои размеры при инициализации экрана или при изменении размера содержимого.
Фиксированный размер
Фиксированный размер подразумевает, что размеры компонента не будут изменяться во время выполнения.
<vbox width="20em" height="15em"/>
vBox.setWidth("20em");
vBox.setHeight("15em");
Размер можно установить, используя абсолютные (например, px) или относительные (например, em) единицы длины. Все экраны и компоненты платформы используют относительные единицы длины, такие как em и rem, поэтому можно изменить размер всего приложения.
em - это единица измерения размера, относительная размера шрифта родителя. По умолчанию размер шрифта - 16px. Для информации о единицах измерения см. CSS values and units.
|
Относительный размер
Относительный размер указывает процент доступного пространства, которое будет занимать компонент.
<button text="Button" width="50%"/>
button.setWidth("50%");
Компоненты с относительным размером будут реагировать на изменения доступного пространства и автоматически изменять свой фактический размер на экране.
Специфика контейнеров
-
Корневой элемент
layout- это вертикальный контейнер (vbox), который по умолчанию имеет ширину и высоту 100%. -
scrollerдолжен иметь фиксированную или относительную (но неAUTO) ширину и высоту. Компоненты внутриscroller, расположенные в направлении прокрутки, не должны иметь относительного размера.
Специфика компонентов
-
Для
dataGridне требуется явно присваиватьheight="100%"или расширять его внутриvboxили корневого элементаlayout, потому что его CSS-свойство flex-grow установлено в 1, что означает, что по умолчанию компонент уже расширен в родительском контейнере. Тем не менее, дляdataGridрекомендуется установить атрибутminHeight, чтобы предотвратить коллапс компонента, если вертикального пространства недостаточно.
Расширение компонентов
Компоненты могут быть настроены на расширение и занятие всего дополнительного пространства, которое есть у контейнера.
<hbox expand="btn" padding="true" width="100%">
<button text="Button"/>
<button id="btn" text="Button"/>
<button text="Button"/>
</hbox>
<vbox expand="btn" width="100%" minHeight="20em">
<button text="Button"/>
<button id="btn" text="Button"/>
<button text="Button"/>
</vbox>
Расширение компонента фактически означает, что его CSS-свойство flex-grow установлено в 1.
|
Интервалы и отступы
С помощью атрибутов spacing, margin и padding можно определить пустое пространство вокруг компонентов и внутри них.
Spacing
Атрибут spacing переключает для компонента настройку spacing темы. Если тема поддерживает этот атрибут, то для компонента применятся или удалятся интервалы.
Интервал включен по умолчанию для компонентов vbox и hbox.
Варианты интервалов
Атрибут spacing неявно добавляет средний интервал к теме компонента, что эквивалентно определению themeNames="spacing". Для установки других вариантов используйте атрибут themeNames явно. Доступно пять различных вариантов интервалов:
| Вариант темы | Рекомендации по использованию |
|---|---|
spacing-xs |
Очень маленький интервал между элементами |
spacing-s |
Небольшой интервал между элементами |
spacing |
Средний интервал между элементами |
spacing-l |
Большой интервал между элементами |
spacing-xl |
Очень большой интервал между элементами |
Пример добавления интервала spacing-xl:
<vbox themeNames="spacing-xl" alignItems="STRETCH">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
Padding
Атрибут padding позволяет задавать пространство между границами контейнера и вложенными компонентами.
По умолчанию padding включен для vbox. Его можно отключить, установив атрибут padding в false. Для hbox по умолчанию padding отключен и его можно включить, установив атрибут padding в true.
Выравнивание
Режим JustifyContent
Атрибут justifyContent соответствует CSS-свойству justify-content, которое определяет, как браузер распределяет пространство между и вокруг элементов контента вдоль главной оси flex-контейнера.
| Значение | Описание |
|---|---|
|
Элементы размещаются в начале контейнера. |
|
Элементы размещаются в центре контейнера. |
|
Элементы размещаются в конце контейнера. |
|
Элементы размещаются с пространством между строками; первый элемент на начальной линии, последний элемент на конечной линии. |
|
Элементы равномерно размещаются в линии с равным пространством вокруг них. Обратите внимание, что промежутки в начале и конце равны половине размера пространства между каждым элементом. |
|
Элементы размещаются так, чтобы пространство между любыми двумя элементами (и пространство до краев) было равным. |
Для vbox и flexLayout с flexDirection="COLUMN" (то есть при flex-direction: column) атрибут justifyContent работает следующим образом:
<vbox justifyContent="START" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
justifyContent="START"<vbox justifyContent="CENTER" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
justifyContent="CENTER"<vbox justifyContent="END" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
justifyContent="END"<vbox justifyContent="BETWEEN" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
justifyContent="BETWEEN"<vbox justifyContent="AROUND" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
justifyContent="AROUND"<vbox justifyContent="EVENLY" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
justifyContent="EVENLY"Для hbox и flexLayout с flexDirection="ROW" (то есть при flex-direction: row) атрибут justifyContent работает следующим образом:
<hbox justifyContent="START" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
justifyContent="START"<hbox justifyContent="CENTER" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
justifyContent="CENTER"<hbox justifyContent="END" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
justifyContent="END"<hbox justifyContent="BETWEEN" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
justifyContent="BETWEEN"<hbox justifyContent="AROUND" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
justifyContent="AROUND"<hbox justifyContent="EVENLY" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
justifyContent="EVENLY"AlignItems
Атрибут alignItems соответствует CSS-свойству align-items, которое определяет поведение по умолчанию для размещения элементов flex-контейнера вдоль поперечной оси на текущей линии. Можно рассматривать его как версию justify-content для поперечной оси (перпендикулярной главной оси).
| Значение | Описание |
|---|---|
|
Элементы размещаются в начале поперечной оси. |
|
Элементы центрируются в поперечной оси. |
|
Элементы размещаются в конце поперечной оси. |
|
Элементы с неопределенным размером вдоль поперечной оси растягиваются, чтобы соответствовать контейнеру. |
|
Элементы размещаются на базовой линии контейнера. Работает только для |
|
Элемент наследует свойство align-items своего родительского контейнера или "stretch", если у него нет родительского контейнера. |
Для vbox и flexLayout с flexDirection="COLUMN" (когда flex-direction: column), атрибут alignItems работает следующим образом:
<vbox alignItems="START">
<button text="Button" width="6em"/>
<button text="Button" width="7em"/>
<button text="Button" width="5em"/>
</vbox>
alignItems="START"<vbox alignItems="CENTER">
<button text="Button" width="6em"/>
<button text="Button" width="7em"/>
<button text="Button" width="5em"/>
</vbox>
alignItems="CENTER"<vbox alignItems="END">
<button text="Button" width="6em"/>
<button text="Button" width="7em"/>
<button text="Button" width="5em"/>
</vbox>
alignItems="END"<vbox alignItems="STRETCH">
<button text="Button" width="AUTO"/>
<button text="Button" width="AUTO"/>
<button text="Button" width="AUTO"/>
</vbox>
alignItems="STRETCH"Для hbox и flexLayout с flexDirection="ROW" (когда flex-direction: row), атрибут alignItems работает следующим образом:
<hbox alignItems="START" padding="true" width="100%" minHeight="10em">
<button text="Button" height="2em"/>
<button text="Button" height="3em"/>
<button text="Button" height="1.5em"/>
</hbox>
alignItems="START"<hbox alignItems="CENTER" padding="true" width="100%" minHeight="10em">
<button text="Button" height="2em"/>
<button text="Button" height="3em"/>
<button text="Button" height="1.5em"/>
</hbox>
alignItems="CENTER"<hbox alignItems="END" padding="true" width="100%" minHeight="10em">
<button text="Button" height="2em"/>
<button text="Button" height="3em"/>
<button text="Button" height="1.5em"/>
</hbox>
alignItems="END"<hbox alignItems="STRETCH" padding="true" width="100%" minHeight="10em">
<button text="Button" height="AUTO"/>
<button text="Button" height="AUTO"/>
<button text="Button" height="AUTO"/>
</hbox>
alignItems="STRETCH"<hbox alignItems="BASELINE" padding="true" width="100%" minHeight="10em">
<button text="Button" height="2em"/>
<button text="Button" height="3em"/>
<button text="Button" height="1.5em"/>
</hbox>
alignItems="BASELINE"AlignSelf
Атрибут alignSelf соответствует CSS-свойству align-self, которое определяет выравнивание отдельных компонентов внутри контейнера. Это индивидуальное выравнивание компонента переопределяет любое выравнивание, установленное с помощью alignItems.
<vbox alignItems="START">
<button text="alignSelf=END" alignSelf="END"/>
<button text="alignSelf=CENTER" alignSelf="CENTER"/>
<button text="alignSelf=AUTO" alignSelf="AUTO"/>
</vbox>
alignItems="START" и разным alignSelf для вложенных компонентов<hbox alignItems="START" justifyContent="BETWEEN" padding="true" width="100%" minHeight="10em">
<button text="alignSelf=END" alignSelf="END"/>
<button text="alignSelf=CENTER" alignSelf="CENTER"/>
<button text="alignSelf=AUTO" alignSelf="AUTO"/>
</hbox>
alignItems="START" и разным alignSelf для вложенных компонентовРаспространенные ошибки компоновки
Ошибка 1. Установка относительного размера для компонента в контейнере с размером, основанным на содержимом
<vbox>
<dataGrid id="usersDataGrid" dataContainer="usersDc"
width="100%" height="100%">
<actions/>
<columns>
<column property="firstName"/>
<column property="lastName"/>
<column property="username"/>
</columns>
</dataGrid>
</vbox>
В этом примере dataGrid имеет высоту 100%, в то время как высота по умолчанию для vbox - AUTO, т.е. основана на содержимом. В результате dataGrid коллапсирует.
Ошибка 2. Не отключенный отступ для вложенных контейнеров vbox
<layout>
<genericFilter ...>
...
</genericFilter>
<vbox width="100%">
<hbox id="buttonsPanel" classNames="buttons-panel">
...
</hbox>
<dataGrid id="usersDataGrid" ...>
...
</dataGrid>
</vbox>
<hbox>
...
</hbox>
</layout>
В этом примере dataGrid и hbox размещены внутри vbox, который по умолчанию имеет включенный отступ. В результате компоненты внутри vbox не выравниваются с компонентами снаружи.
Ошибка 3. Выравнивание компонентов с относительным размером
<hbox alignItems="CENTER" padding="true" width="100%" minHeight="10em">
<span text="Span" height="100%"/>
</hbox>
В этом примере span имеет высоту 100% в контейнере hbox, который определяет alignItems="CENTER". В результате текст размещается в верхнем левом углу.
Ошибка 4. Растягивание компонентов с фиксированным размером
<hbox alignItems="STRETCH" padding="true" width="100%" minHeight="10em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
В этом примере кнопки имеют высоту, заданную в стилях по умолчанию. В результате кнопки не растягиваются по вертикали.
Ошибка 5. Установка размера без единиц измерения
<textField width="400"/>
В этом примере у textField не указаны единицы измерения размера. В результате значение размера игнорируется.
Советы и хитрости
Адаптация к экранам разного размера
Пример определения адаптивного текстового поля с фиксированным размером на больших экранах и шириной 100% на маленьких:
<hbox width="100%">
<textField width="100%" maxWidth="40em"/>
<button text="Button"/>
</hbox>
Пример определения formLayout с одной колонкой фиксированного размера на больших экранах и шириной 100% на маленьких:
<formLayout id="form"
dataContainer="taskTypeDc"
classNames="mx-m"
maxWidth="40em"> (2)
<responsiveSteps>
<responsiveStep minWidth="0" columns="1"/> (1)
</responsiveSteps>
<textField id="nameField" property="name"/>
<textArea id="descriptionField" property="description"
height="9.5em"/>
</formLayout>
| 1 | Определение того, что formLayout должен иметь одну колонку для любого размера экрана. |
| 2 | Установка максимальной ширины. |
Использование утилитных классов Lumo
Для простой стилизации можно использовать утилитные классы Lumo, предоставляемые Vaadin. Они представляют собой предопределенные классы CSS, решающие типовые задачи.
Каждый утилитный класс применяет определенный стиль к элементу, например, цвет фона, границы, шрифты, размеры или отступы. Доступны также классы для применения функций CSS flexbox и grid.
Java-класс LumoUtility содержит строковые константы для всех утилитных классов. Они разделены на вложенные классы категорий, например, LumoUtility.Margin.
Пример использования утилитных классов Lumo для добавления закругленной границы контейнеру:
<vbox id="imageWrapper"
classNames="border (1)
rounded-m (2)
border-contrast-20" (3)
alignItems="CENTER"
width="100%" maxWidth="30em">
| 1 | Добавляет границу с цветом границы по умолчанию |
| 2 | Устанавливает радиус границы равный var(--lumo-border-radius-m) |
| 3 | Устанавливает цвет границы равный var(--lumo-contrast-20pct) |
Пример выравнивания компонента в конец горизонтального контейнера:
<header id="header" classNames="jmix-main-view-header">
<drawerToggle id="drawerToggle"
classNames="jmix-main-view-drawer-toggle"
themeNames="contrast"
ariaLabel="msg://drawerToggle.ariaLabel"/>
<h1 id="viewTitle" classNames="jmix-main-view-title"/>
<button id="logoutButton" icon="SIGN_OUT" classNames="ms-auto me-s"/> (1)
</header>
| 1 | ms-auto эквивалентно margin-inline-start: auto, т.е. определяет отступ в логическом начале элемента, которое сопоставляется с физическим отступом в зависимости от flex-direction; me-s эквивалентно margin-inline-end: var(--lumo-space-s), т. е. определяет отступ в логическом конце элемента. |