Правила компоновки
Этот раздел объясняет методы позиционирования визуальных компонентов и контейнеров в экранах.
Размеры компонентов
Компоненты, реализующие com.vaadin.flow.component.HasSize
(например, button, textField, dataGrid, vbox, etc.) имеют следующие общие атрибуты: width, minWidth, maxWidth, height, minHeight, maxHeight. Эти атрибуты прямо соответствуют соответствующим по имени свойствам CSS.
Атрибуты min/max размеров помогают в создании адаптивного дизайна, когда компоненты должны приспосабливаться к разным размерам экрана. Эти атрибуты также могут использоваться для предотвращения переполнения компонентов или их слишком большого размера. См. практический пример ниже. |
Размеры компонентов могут быть следующих типов:
-
Основанные на содержимом -
AUTO
-
Фиксированные, например,
25em
-
Относительные (в процентах) к родительскому контейнеру, например,
100%
![size types](../_images/layout-rules/size-types.png)
Значение размера должно быть корректной для CSS строкой размера. |
Размер, основанный на содержимом
Компонент займет достаточно места, чтобы вместить свое содержимое.
Примеры:
-
Для
button
размер определяется длиной значения атрибутаtext
. -
Для контейнеров (layouts) размер определяется суммой всех размеров компонентов внутри контейнера.
<button text="Button" width="AUTO"/>
button.setWidth("AUTO");
Компоненты с размером, основанным на содержимом, будут автоматически изменять свои размеры при инициализации экрана или при изменении размера содержимого.
![content based size](../_images/layout-rules/content-based-size.png)
Фиксированный размер
Фиксированный размер подразумевает, что размеры компонента не будут изменяться во время выполнения.
<vbox width="20em" height="15em"/>
vBox.setWidth("20em");
vBox.setHeight("15em");
![fixed size](../_images/layout-rules/fixed-size.png)
Размер можно установить, используя абсолютные (например, px
) или относительные (например, em
) единицы длины. Все экраны и компоненты платформы используют относительные единицы длины, такие как em
и rem
, поэтому можно изменить размер всего приложения.
em - это единица измерения размера, относительная размера шрифта родителя. По умолчанию размер шрифта - 16px . Для информации о единицах измерения см. CSS values and units.
|
Относительный размер
Относительный размер указывает процент доступного пространства, которое будет занимать компонент.
<button text="Button" width="50%"/>
button.setWidth("50%");
Компоненты с относительным размером будут реагировать на изменения доступного пространства и автоматически изменять свой фактический размер на экране.
![relative size](../_images/layout-rules/relative-size.png)
Специфика контейнеров
-
Корневой элемент
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>
![hbox expand](../_images/layout-rules/hbox-expand.png)
<vbox expand="btn" width="100%" minHeight="20em">
<button text="Button"/>
<button id="btn" text="Button"/>
<button text="Button"/>
</vbox>
![vbox expand](../_images/layout-rules/vbox-expand.png)
Расширение компонента фактически означает, что его CSS-свойство flex-grow установлено в 1 .
|
Интервалы и отступы
С помощью атрибутов spacing
, margin
и padding
можно определить пустое пространство вокруг компонентов и внутри них.
Spacing
Атрибут spacing
переключает для компонента настройку spacing
темы. Если тема поддерживает этот атрибут, то для компонента применятся или удалятся интервалы.
![hbox no spacing](../_images/layout-rules/hbox-no-spacing.png)
![hbox spacing](../_images/layout-rules/hbox-spacing.png)
![vbox spacing](../_images/layout-rules/vbox-spacing.png)
Интервал включен по умолчанию для компонентов 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>
![vbox spacing xl](../_images/layout-rules/vbox-spacing-xl.png)
Padding
Атрибут padding
позволяет задавать пространство между границами контейнера и вложенными компонентами.
![vbox padding](../_images/layout-rules/vbox-padding.png)
По умолчанию 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>
![vbox justifyContent start](../_images/layout-rules/vbox-justifyContent-start.png)
justifyContent="START"
<vbox justifyContent="CENTER" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
![vbox justifyContent center](../_images/layout-rules/vbox-justifyContent-center.png)
justifyContent="CENTER"
<vbox justifyContent="END" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
![vbox justifyContent end](../_images/layout-rules/vbox-justifyContent-end.png)
justifyContent="END"
<vbox justifyContent="BETWEEN" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
![vbox justifyContent between](../_images/layout-rules/vbox-justifyContent-between.png)
justifyContent="BETWEEN"
<vbox justifyContent="AROUND" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
![vbox justifyContent around](../_images/layout-rules/vbox-justifyContent-around.png)
justifyContent="AROUND"
<vbox justifyContent="EVENLY" minHeight="20em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</vbox>
![vbox justifyContent evenly](../_images/layout-rules/vbox-justifyContent-evenly.png)
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>
![hbox justifyContent start](../_images/layout-rules/hbox-justifyContent-start.png)
justifyContent="START"
<hbox justifyContent="CENTER" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
![hbox justifyContent center](../_images/layout-rules/hbox-justifyContent-center.png)
justifyContent="CENTER"
<hbox justifyContent="END" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
![hbox justifyContent end](../_images/layout-rules/hbox-justifyContent-end.png)
justifyContent="END"
<hbox justifyContent="BETWEEN" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
![hbox justifyContent between](../_images/layout-rules/hbox-justifyContent-between.png)
justifyContent="BETWEEN"
<hbox justifyContent="AROUND" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
![hbox justifyContent around](../_images/layout-rules/hbox-justifyContent-around.png)
justifyContent="AROUND"
<hbox justifyContent="EVENLY" padding="true" width="100%">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
![hbox justifyContent evenly](../_images/layout-rules/hbox-justifyContent-evenly.png)
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>
![vbox alignItems start](../_images/layout-rules/vbox-alignItems-start.png)
alignItems="START"
<vbox alignItems="CENTER">
<button text="Button" width="6em"/>
<button text="Button" width="7em"/>
<button text="Button" width="5em"/>
</vbox>
![vbox alignItems center](../_images/layout-rules/vbox-alignItems-center.png)
alignItems="CENTER"
<vbox alignItems="END">
<button text="Button" width="6em"/>
<button text="Button" width="7em"/>
<button text="Button" width="5em"/>
</vbox>
![vbox alignItems end](../_images/layout-rules/vbox-alignItems-end.png)
alignItems="END"
<vbox alignItems="STRETCH">
<button text="Button" width="AUTO"/>
<button text="Button" width="AUTO"/>
<button text="Button" width="AUTO"/>
</vbox>
![vbox alignItems stretch](../_images/layout-rules/vbox-alignItems-stretch.png)
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>
![hbox alignItems start](../_images/layout-rules/hbox-alignItems-start.png)
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>
![hbox alignItems center](../_images/layout-rules/hbox-alignItems-center.png)
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>
![hbox alignItems end](../_images/layout-rules/hbox-alignItems-end.png)
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>
![hbox alignItems stretch](../_images/layout-rules/hbox-alignItems-stretch.png)
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>
![hbox alignItems baseline](../_images/layout-rules/hbox-alignItems-baseline.png)
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>
![vbox alignSelf](../_images/layout-rules/vbox-alignSelf.png)
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>
![hbox alignSelf](../_images/layout-rules/hbox-alignSelf.png)
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
коллапсирует.
![dataGrid relative size](../_images/layout-rules/dataGrid-relative-size.png)
Ошибка 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
не выравниваются с компонентами снаружи.
![vbox incorrect padding](../_images/layout-rules/vbox-incorrect-padding.png)
Ошибка 3. Выравнивание компонентов с относительным размером
<hbox alignItems="CENTER" padding="true" width="100%" minHeight="10em">
<span text="Span" height="100%"/>
</hbox>
В этом примере span
имеет высоту 100% в контейнере hbox
, который определяет alignItems="CENTER"
. В результате текст размещается в верхнем левом углу.
![relative size alignment](../_images/layout-rules/relative-size-alignment.png)
Ошибка 4. Растягивание компонентов с фиксированным размером
<hbox alignItems="STRETCH" padding="true" width="100%" minHeight="10em">
<button text="Button"/>
<button text="Button"/>
<button text="Button"/>
</hbox>
В этом примере кнопки имеют высоту, заданную в стилях по умолчанию. В результате кнопки не растягиваются по вертикали.
![fixed size stretching](../_images/layout-rules/fixed-size-stretching.png)
Ошибка 5. Установка размера без единиц измерения
<textField width="400"/>
В этом примере у textField
не указаны единицы измерения размера. В результате значение размера игнорируется.
Советы и хитрости
Адаптация к экранам разного размера
Пример определения адаптивного текстового поля с фиксированным размером на больших экранах и шириной 100% на маленьких:
<hbox width="100%">
<textField width="100%" maxWidth="40em"/>
<button text="Button"/>
</hbox>
![responsive text field](../_images/layout-rules/responsive-text-field.gif)
Пример определения 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 | Установка максимальной ширины. |
![single column formLayout](../_images/layout-rules/single-column-formLayout.gif)
Использование утилитных классов 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) |
![LumoUtility example](../_images/layout-rules/LumoUtility-example.png)
Пример выравнивания компонента в конец горизонтального контейнера:
<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) , т. е. определяет отступ в логическом конце элемента. |
![align to end](../_images/layout-rules/align-to-end.png)