1# Relative Layout (RelativeContainer)
2
3
4## Overview
5
6During application development, nesting components – same or different – is common in page layout, especially when the target page is complicated. Yet, nesting components too deeply, or nesting too many components, can be especially expensive. Naturally, optimizing the layout hierarchies can effectively lead to better performance and less time overhead. <!--Del-->For details about how the relative container is more performance-efficient than the list, see [Improving Layout Performance](../performance/reduce-view-nesting-levels.md).<!--DelEnd-->
7
8The relative layout, implemented using the **RelativeContainer** container component, is used to lay out child elements in relative positions. It is applicable to element alignment in complex scenarios. A child element can use the container or another child element as the anchor, based on which its relative position is determined. Below shows a relative layout. The dotted lines in the figure indicate the position dependency.
9
10
11  **Figure 1** Relative layout
12
13![relative-layout](figures/relative-layout.png)
14
15
16A child element does not necessarily adopt the dependency shown above to determine its relative position. For example, Item4 may use Item2 or the **RelativeContainer** parent container as a dependency anchor.
17
18
19## Basic Concepts
20
21- Anchor: element relative to which an element's position is specified.
22
23- Alignment mode: how the current element is aligned with the anchor, which can be top-, center-, or bottom-aligned in the vertical direction or left-, center-, and right-aligned in the horizontal direction.
24
25
26## Setting the Dependency
27
28
29### Setting the Anchor
30
31By setting the anchor, you set a position dependency relationship between a child element and its parent element or sibling elements. In the horizontal direction, you can set the left, middle, and right anchors. In the vertical direction, you can set the top, center, and bottom anchors.
32To specify anchors, you must set IDs for the **RelativeContainer** component and its child elements. The default ID is **\_\_container\_\_**, and the IDs for the remaining child elements are set through the **id** attribute.  Components without **id** set can be displayed but cannot be used as anchors by other child components; the relative layout container will generate an ID for them, and the pattern of this ID is not predictable by the application logic. When a mutual or circular dependency occurs, none of the child components in the container are drawn. If anchors are set for more than two positions in a single direction but the anchor positions are reversed, the size of the child component is 0, which means that the child component is not drawn.
33
34>**NOTE**
35>
36>When using anchors, pay attention to the relative positions of child elements to avoid misplacement or blocking.
37
38- The ID of the **RelativeContainer** parent component is **__container__**.
39
40  ```ts
41  let AlignRus: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
42    'top': { 'anchor': '__container__', 'align': VerticalAlign.Top },
43    'left': { 'anchor': '__container__', 'align': HorizontalAlign.Start }
44  }
45  let AlignRue: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
46    'top': { 'anchor': '__container__', 'align': VerticalAlign.Top },
47    'right': { 'anchor': '__container__', 'align': HorizontalAlign.End }
48  }
49  let Mleft: Record<string, number> = { 'left': 20 }
50  let BWC: Record<string, number | string> = { 'width': 2, 'color': '#6699FF' }
51
52  @Entry
53  @Component
54  struct Index {
55    build() {
56      RelativeContainer() {
57        Row() {
58          Text('row1')
59        }
60        .justifyContent(FlexAlign.Center)
61        .width(100)
62        .height(100)
63        .backgroundColor('#a3cf62')
64        .alignRules(AlignRus)
65        .id("row1")
66
67        Row() {
68          Text('row2')
69        }
70        .justifyContent(FlexAlign.Center)
71        .width(100)
72        .height(100)
73        .backgroundColor('#00ae9d')
74        .alignRules(AlignRue)
75        .id("row2")
76      }.width(300).height(300)
77      .margin(Mleft)
78      .border(BWC)
79    }
80  }
81  ```
82
83  ![en-us_image_0000001562820901](figures/en-us_image_0000001562820901.png)
84
85- Example of using a sibling element as the anchor:
86
87  ```ts
88  let AlignRus: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
89    'top': { 'anchor': '__container__', 'align': VerticalAlign.Top },
90    'left': { 'anchor': '__container__', 'align': HorizontalAlign.Start }
91  }
92  let RelConB: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
93    'top': { 'anchor': 'row1', 'align': VerticalAlign.Bottom },
94    'left': { 'anchor': 'row1', 'align': HorizontalAlign.Start }
95  }
96  let Mleft: Record<string, number> = { 'left': 20 }
97  let BWC: Record<string, number | string> = { 'width': 2, 'color': '#6699FF' }
98
99  @Entry
100  @Component
101  struct Index {
102    build() {
103      RelativeContainer() {
104        Row() {
105          Text('row1')
106        }
107        .justifyContent(FlexAlign.Center)
108        .width(100)
109        .height(100)
110        .backgroundColor('#00ae9d')
111        .alignRules(AlignRus)
112        .id("row1")
113
114        Row() {
115          Text('row2')
116        }
117        .justifyContent(FlexAlign.Center)
118        .width(100)
119        .height(100)
120        .backgroundColor('#a3cf62')
121        .alignRules(RelConB)
122        .id("row2")
123      }.width(300).height(300)
124      .margin(Mleft)
125      .border(BWC)
126    }
127  }
128  ```
129
130  ![en-us_image_0000001562940613](figures/en-us_image_0000001562940613.png)
131
132- Make sure the anchors of a child component do not depend on each other.
133
134  ```ts
135  @Entry
136  @Component
137  struct Index {
138    build() {
139      Row() {
140        RelativeContainer() {
141          Row(){Text('row1')}.justifyContent(FlexAlign.Center).width(100).height(100)
142          .backgroundColor('#a3cf62')
143          .alignRules({
144            top: {anchor: "__container__", align: VerticalAlign.Top},
145            left: {anchor: "__container__", align: HorizontalAlign.Start}
146          })
147          .id("row1")
148
149          Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100)
150          .backgroundColor('#00ae9d')
151          .alignRules({
152            top: {anchor: "__container__", align: VerticalAlign.Top},
153            right: {anchor: "__container__", align: HorizontalAlign.End},
154            bottom: {anchor: "row1", align: VerticalAlign.Center},
155          })
156          .id("row2")
157
158          Row(){Text('row3')}.justifyContent(FlexAlign.Center).height(100)
159          .backgroundColor('#0a59f7')
160          .alignRules({
161            top: {anchor: "row1", align: VerticalAlign.Bottom},
162            left: {anchor: "row1", align: HorizontalAlign.Start},
163            right: {anchor: "row2", align: HorizontalAlign.Start}
164          })
165          .id("row3")
166
167          Row(){Text('row4')}.justifyContent(FlexAlign.Center)
168          .backgroundColor('#2ca9e0')
169          .alignRules({
170            top: {anchor: "row3", align: VerticalAlign.Bottom},
171            left: {anchor: "row1", align: HorizontalAlign.Center},
172            right: {anchor: "row2", align: HorizontalAlign.End},
173            bottom: {anchor: "__container__", align: VerticalAlign.Bottom}
174          })
175          .id("row4")
176        }
177        .width(300).height(300)
178        .margin({left: 50})
179        .border({width:2, color: "#6699FF"})
180      }
181      .height('100%')
182    }
183  }
184  ```
185  ![Simplify-Component-Layout](figures/arkts-simplify-component-layout-image1.png)
186
187### Setting Alignment Relative to the Anchor
188
189After an anchor is set, you can use **align** to set the alignment mode relative to the anchor.
190
191Alignment modes in the horizontal direction can be left, center, or right, achieved by the **HorizontalAlign.Start**, **HorizontalAlign.Center**, and **HorizontalAlign.End** attributes, respectively.
192
193![alignment-relative-anchor-horizontal](figures/alignment-relative-anchor-horizontal.png)
194
195Alignment modes in the vertical direction can be top, center, or bottom, achieved by the **VerticalAlign.Top**, **VerticalAlign.Center**, and **VerticalAlign.Bottom** attributes, respectively.
196
197![alignment-relative-anchor-vertical](figures/alignment-relative-anchor-vertical.png)
198
199### Setting Offset
200
201After being aligned relative to the anchor, a child component may be still not at its target position. In this case, you can set the offset.
202
203  ```ts
204@Entry
205@Component
206struct Index {
207  build() {
208    Row() {
209      RelativeContainer() {
210        Row() {
211          Text('row1')
212        }
213        .justifyContent(FlexAlign.Center)
214        .width(100)
215        .height(100)
216        .backgroundColor('#a3cf62')
217        .alignRules({
218          top: { anchor: "__container__", align: VerticalAlign.Top },
219          left: { anchor: "__container__", align: HorizontalAlign.Start }
220        })
221        .id("row1")
222
223        Row() {
224          Text('row2')
225        }
226        .justifyContent(FlexAlign.Center)
227        .width(100)
228        .backgroundColor('#00ae9d')
229        .alignRules({
230          top: { anchor: "__container__", align: VerticalAlign.Top },
231          right: { anchor: "__container__", align: HorizontalAlign.End },
232          bottom: { anchor: "row1", align: VerticalAlign.Center },
233        })
234        .offset({
235          x: -40,
236          y: -20
237        })
238        .id("row2")
239
240        Row() {
241          Text('row3')
242        }
243        .justifyContent(FlexAlign.Center)
244        .height(100)
245        .backgroundColor('#0a59f7')
246        .alignRules({
247          top: { anchor: "row1", align: VerticalAlign.Bottom },
248          left: { anchor: "row1", align: HorizontalAlign.End },
249          right: { anchor: "row2", align: HorizontalAlign.Start }
250        })
251        .offset({
252          x: -10,
253          y: -20
254        })
255        .id("row3")
256
257        Row() {
258          Text('row4')
259        }
260        .justifyContent(FlexAlign.Center)
261        .backgroundColor('#2ca9e0')
262        .alignRules({
263          top: { anchor: "row3", align: VerticalAlign.Bottom },
264          bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
265          left: { anchor: "__container__", align: HorizontalAlign.Start },
266          right: { anchor: "row1", align: HorizontalAlign.End }
267        })
268        .offset({
269          x: -10,
270          y: -30
271        })
272        .id("row4")
273
274        Row() {
275          Text('row5')
276        }
277        .justifyContent(FlexAlign.Center)
278        .backgroundColor('#30c9f7')
279        .alignRules({
280          top: { anchor: "row3", align: VerticalAlign.Bottom },
281          bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
282          left: { anchor: "row2", align: HorizontalAlign.Start },
283          right: { anchor: "row2", align: HorizontalAlign.End }
284        })
285        .offset({
286          x: 10,
287          y: 20
288        })
289        .id("row5")
290
291        Row() {
292          Text('row6')
293        }
294        .justifyContent(FlexAlign.Center)
295        .backgroundColor('#ff33ffb5')
296        .alignRules({
297          top: { anchor: "row3", align: VerticalAlign.Bottom },
298          bottom: { anchor: "row4", align: VerticalAlign.Bottom },
299          left: { anchor: "row3", align: HorizontalAlign.Start },
300          right: { anchor: "row3", align: HorizontalAlign.End }
301        })
302        .offset({
303          x: -15,
304          y: 10
305        })
306        .backgroundImagePosition(Alignment.Bottom)
307        .backgroundImageSize(ImageSize.Cover)
308        .id("row6")
309      }
310      .width(300).height(300)
311      .margin({ left: 50 })
312      .border({ width: 2, color: "#6699FF" })
313    }
314    .height('100%')
315  }
316}
317  ```
318  ![Simplify-Component-Layout](figures/arkts-simplify-component-layout-image2.png)
319
320## Aligning Components in Multiple Layouts
321
322You can set components in multiple layout components, such as **Row**, **Column**, **Flex**, and **Stack**, to be aligned based on the relative layout rules.
323
324  ```ts
325@Entry
326@Component
327struct Index {
328  @State value: number = 0
329
330  build() {
331    Row() {
332
333      RelativeContainer() {
334        Row()
335          .width(100)
336          .height(100)
337          .backgroundColor('#a3cf62')
338          .alignRules({
339            top: { anchor: "__container__", align: VerticalAlign.Top },
340            left: { anchor: "__container__", align: HorizontalAlign.Start }
341          })
342          .id("row1")
343
344        Column()
345          .width('50%')
346          .height(30)
347          .backgroundColor('#00ae9d')
348          .alignRules({
349            top: { anchor: "__container__", align: VerticalAlign.Top },
350            left: { anchor: "__container__", align: HorizontalAlign.Center }
351          })
352          .id("row2")
353
354        Flex({ direction: FlexDirection.Row }) {
355          Text('1').width('20%').height(50).backgroundColor('#0a59f7')
356          Text('2').width('20%').height(50).backgroundColor('#2ca9e0')
357          Text('3').width('20%').height(50).backgroundColor('#0a59f7')
358          Text('4').width('20%').height(50).backgroundColor('#2ca9e0')
359        }
360        .padding(10)
361        .backgroundColor('#30c9f7')
362        .alignRules({
363          top: { anchor: "row2", align: VerticalAlign.Bottom },
364          left: { anchor: "__container__", align: HorizontalAlign.Start },
365          bottom: { anchor: "__container__", align: VerticalAlign.Center },
366          right: { anchor: "row2", align: HorizontalAlign.Center }
367        })
368        .id("row3")
369
370        Stack({ alignContent: Alignment.Bottom }) {
371          Text('First child, show in bottom').width('90%').height('100%').backgroundColor('#a3cf62').align(Alignment.Top)
372          Text('Second child, show in top').width('70%').height('60%').backgroundColor('#00ae9d').align(Alignment.Top)
373        }
374        .margin({ top: 5 })
375        .alignRules({
376          top: { anchor: "row3", align: VerticalAlign.Bottom },
377          left: { anchor: "__container__", align: HorizontalAlign.Start },
378          bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
379          right: { anchor: "row3", align: HorizontalAlign.End }
380        })
381        .id("row4")
382
383      }
384      .width(300).height(300)
385      .margin({ left: 50 })
386      .border({ width: 2, color: "#6699FF" })
387    }
388    .height('100%')
389  }
390}
391  ```
392  ![Simplify-Component-Layout](figures/arkts-simplify-component-layout-image3.png)
393
394## Component Size
395
396The size of a child component is not affected by the relative layout rules. If two or more **alignRule** values are set for a child component in one direction, avoid setting the size in this direction. Otherwise, the component size determined by **alignRule** may conflict with the size you set.
397
398  ```ts
399@Entry
400@Component
401struct Index {
402  build() {
403    Row() {
404      RelativeContainer() {
405        Row() {
406          Text('row1')
407        }
408        .justifyContent(FlexAlign.Center)
409        .width(100)
410        .height(100)
411        .backgroundColor('#a3cf62')
412        .alignRules({
413          top: { anchor: "__container__", align: VerticalAlign.Top },
414          left: { anchor: "__container__", align: HorizontalAlign.Start }
415        })
416        .id("row1")
417
418        Row() {
419          Text('row2')
420        }
421        .justifyContent(FlexAlign.Center)
422        .width(100)
423        .backgroundColor('#00ae9d')
424        .alignRules({
425          top: { anchor: "__container__", align: VerticalAlign.Top },
426          right: { anchor: "__container__", align: HorizontalAlign.End },
427          bottom: { anchor: "row1", align: VerticalAlign.Center },
428        })
429        .id("row2")
430
431        Row() {
432          Text('row3')
433        }
434        .justifyContent(FlexAlign.Center)
435        .height(100)
436        .backgroundColor('#0a59f7')
437        .alignRules({
438          top: { anchor: "row1", align: VerticalAlign.Bottom },
439          left: { anchor: "row1", align: HorizontalAlign.End },
440          right: { anchor: "row2", align: HorizontalAlign.Start }
441        })
442        .id("row3")
443
444        Row() {
445          Text('row4')
446        }.justifyContent(FlexAlign.Center)
447        .backgroundColor('#2ca9e0')
448        .alignRules({
449          top: { anchor: "row3", align: VerticalAlign.Bottom },
450          bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
451          left: { anchor: "__container__", align: HorizontalAlign.Start },
452          right: { anchor: "row1", align: HorizontalAlign.End }
453        })
454        .id("row4")
455
456        Row() {
457          Text('row5')
458        }.justifyContent(FlexAlign.Center)
459        .backgroundColor('#30c9f7')
460        .alignRules({
461          top: { anchor: "row3", align: VerticalAlign.Bottom },
462          bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
463          left: { anchor: "row2", align: HorizontalAlign.Start },
464          right: { anchor: "row2", align: HorizontalAlign.End }
465        })
466        .id("row5")
467
468        Row() {
469          Text('row6')
470        }
471        .justifyContent(FlexAlign.Center)
472        .backgroundColor('#ff33ffb5')
473        .alignRules({
474          top: { anchor: "row3", align: VerticalAlign.Bottom },
475          bottom: { anchor: "row4", align: VerticalAlign.Bottom },
476          left: { anchor: "row3", align: HorizontalAlign.Start },
477          right: { anchor: "row3", align: HorizontalAlign.End }
478        })
479        .id("row6")
480        .backgroundImagePosition(Alignment.Bottom)
481        .backgroundImageSize(ImageSize.Cover)
482      }
483      .width(300).height(300)
484      .margin({ left: 50 })
485      .border({ width: 2, color: "#6699FF" })
486    }
487    .height('100%')
488  }
489}
490  ```
491  ![Simplify-Component-Layout](figures/arkts-simplify-component-layout-image4.png)
492