Правила компоновки
Этот раздел объясняет методы позиционирования визуальных компонентов и контейнеров в экранах.
Размеры компонентов
Компоненты, реализующие 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.
|
Вы можете столкнуться с ситуацией, когда вы устанавливаете фиксированный размер для компонента, например, ширины, но он становится меньше, если в родительском контейнере недостаточно места. Чтобы обойти это, можно либо установить значения minWidth /minHeight такими же, как значения width /height , либо установить flex-shrink: 0 , используя атрибут css.Это происходит потому, что когда компоненты размещены в контейнерах flexbox, таких как hbox, vbox или flexLayout , то даже если у них фиксированный размер вдоль главной оси контейнера, их размер не может превышать размер родительского контейнера. Согласно спецификации, начальное значение свойства flex-shrink равно 1, что означает, что по умолчанию flex-item уменьшает свой размер, если доступного места недостаточно.
|
Относительный размер
Относительный размер указывает процент доступного пространства, которое будет занимать компонент.
<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) , т. е. определяет отступ в логическом конце элемента. |
