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 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(){Text('row1')}.justifyContent(FlexAlign.Center).width(100).height(100) 58 .backgroundColor("#FF3333") 59 .alignRules(AlignRus) 60 .id("row1") 61 62 Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100).height(100) 63 .backgroundColor("#FFCC00") 64 .alignRules(AlignRue) 65 .id("row2") 66 }.width(300).height(300) 67 .margin(Mleft) 68 .border(BWC) 69 } 70 } 71 ``` 72 73  74 75- Example of using a sibling element as the anchor: 76 77 ```ts 78 let AlignRus:Record<string,Record<string,string|VerticalAlign|HorizontalAlign>> = { 79 'top': { 'anchor': '__container__', 'align': VerticalAlign.Top }, 80 'left': { 'anchor': '__container__', 'align': HorizontalAlign.Start } 81 } 82 let RelConB:Record<string,Record<string,string|VerticalAlign|HorizontalAlign>> = { 83 'top': { 'anchor': 'row1', 'align': VerticalAlign.Bottom }, 84 'left' : { 'anchor': 'row1', 'align': HorizontalAlign.Start } 85 } 86 let Mleft:Record<string,number> = { 'left': 20 } 87 let BWC:Record<string,number|string> = { 'width': 2, 'color': '#6699FF' } 88 89 @Entry 90 @Component 91 struct Index { 92 build() { 93 RelativeContainer() { 94 Row(){Text('row1')}.justifyContent(FlexAlign.Center).width(100).height(100) 95 .backgroundColor("#FF3333") 96 .alignRules(AlignRus) 97 .id("row1") 98 99 Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100).height(100) 100 .backgroundColor("#FFCC00") 101 .alignRules(RelConB) 102 .id("row2") 103 }.width(300).height(300) 104 .margin(Mleft) 105 .border(BWC) 106 } 107 } 108 ``` 109 110  111 112- Make sure the anchors of a child component do not depend on each other. 113 114 ```ts 115 @Entry 116 @Component 117 struct Index { 118 build() { 119 Row() { 120 RelativeContainer() { 121 Row(){Text('row1')}.justifyContent(FlexAlign.Center).width(100).height(100) 122 .backgroundColor('#ff3339ff') 123 .alignRules({ 124 top: {anchor: "__container__", align: VerticalAlign.Top}, 125 left: {anchor: "__container__", align: HorizontalAlign.Start} 126 }) 127 .id("row1") 128 129 Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100) 130 .backgroundColor('#ff298e1e') 131 .alignRules({ 132 top: {anchor: "__container__", align: VerticalAlign.Top}, 133 right: {anchor: "__container__", align: HorizontalAlign.End}, 134 bottom: {anchor: "row1", align: VerticalAlign.Center}, 135 }) 136 .id("row2") 137 138 Row(){Text('row3')}.justifyContent(FlexAlign.Center).height(100) 139 .backgroundColor('#ffff6a33') 140 .alignRules({ 141 top: {anchor: "row1", align: VerticalAlign.Bottom}, 142 left: {anchor: "row1", align: HorizontalAlign.Start}, 143 right: {anchor: "row2", align: HorizontalAlign.Start} 144 }) 145 .id("row3") 146 147 Row(){Text('row4')}.justifyContent(FlexAlign.Center) 148 .backgroundColor('#ffff33fd') 149 .alignRules({ 150 top: {anchor: "row3", align: VerticalAlign.Bottom}, 151 left: {anchor: "row1", align: HorizontalAlign.Center}, 152 right: {anchor: "row2", align: HorizontalAlign.End}, 153 bottom: {anchor: "__container__", align: VerticalAlign.Bottom} 154 }) 155 .id("row4") 156 } 157 .width(300).height(300) 158 .margin({left: 50}) 159 .border({width:2, color: "#6699FF"}) 160 } 161 .height('100%') 162 } 163 } 164 ``` 165  166 167### Setting Alignment Relative to the Anchor 168 169After an anchor is set, you can use **align** to set the alignment mode relative to the anchor. 170 171Alignment modes in the horizontal direction can be left, center, or right, achieved by the **HorizontalAlign.Start**, **HorizontalAlign.Center**, and **HorizontalAlign.End** attributes, respectively. 172 173 174 175Alignment modes in the vertical direction can be top, center, or bottom, achieved by the **VerticalAlign.Top**, **VerticalAlign.Center**, and **VerticalAlign.Bottom** attributes, respectively. 176 177 178 179### Setting Offset 180 181After 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. 182 183 ```ts 184 @Entry 185 @Component 186 struct Index { 187 build() { 188 Row() { 189 RelativeContainer() { 190 Row(){Text('row1')}.justifyContent(FlexAlign.Center).width(100).height(100) 191 .backgroundColor("#FF3333") 192 .alignRules({ 193 top: {anchor: "__container__", align: VerticalAlign.Top}, 194 left: {anchor: "__container__", align: HorizontalAlign.Start} 195 }) 196 .id("row1") 197 198 Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100) 199 .backgroundColor("#FFCC00") 200 .alignRules({ 201 top: {anchor: "__container__", align: VerticalAlign.Top}, 202 right: {anchor: "__container__", align: HorizontalAlign.End}, 203 bottom: {anchor: "row1", align: VerticalAlign.Center}, 204 }) 205 .offset({ 206 x:-40, 207 y:-20 208 }) 209 .id("row2") 210 211 Row(){Text('row3')}.justifyContent(FlexAlign.Center).height(100) 212 .backgroundColor("#FF6633") 213 .alignRules({ 214 top: {anchor: "row1", align: VerticalAlign.Bottom}, 215 left: {anchor: "row1", align: HorizontalAlign.End}, 216 right: {anchor: "row2", align: HorizontalAlign.Start} 217 }) 218 .offset({ 219 x:-10, 220 y:-20 221 }) 222 .id("row3") 223 224 Row(){Text('row4')}.justifyContent(FlexAlign.Center) 225 .backgroundColor("#FF9966") 226 .alignRules({ 227 top: {anchor: "row3", align: VerticalAlign.Bottom}, 228 bottom: {anchor: "__container__", align: VerticalAlign.Bottom}, 229 left: {anchor: "__container__", align: HorizontalAlign.Start}, 230 right: {anchor: "row1", align: HorizontalAlign.End} 231 }) 232 .offset({ 233 x:-10, 234 y:-30 235 }) 236 .id("row4") 237 238 Row(){Text('row5')}.justifyContent(FlexAlign.Center) 239 .backgroundColor("#FF66FF") 240 .alignRules({ 241 top: {anchor: "row3", align: VerticalAlign.Bottom}, 242 bottom: {anchor: "__container__", align: VerticalAlign.Bottom}, 243 left: {anchor: "row2", align: HorizontalAlign.Start}, 244 right: {anchor: "row2", align: HorizontalAlign.End} 245 }) 246 .offset({ 247 x:10, 248 y:20 249 }) 250 .id("row5") 251 252 Row(){Text('row6')}.justifyContent(FlexAlign.Center) 253 .backgroundColor('#ff33ffb5') 254 .alignRules({ 255 top: {anchor: "row3", align: VerticalAlign.Bottom}, 256 bottom: {anchor: "row4", align: VerticalAlign.Bottom}, 257 left: {anchor: "row3", align: HorizontalAlign.Start}, 258 right: {anchor: "row3", align: HorizontalAlign.End} 259 }) 260 .offset({ 261 x:-15, 262 y:10 263 }) 264 .backgroundImagePosition(Alignment.Bottom) 265 .backgroundImageSize(ImageSize.Cover) 266 .id("row6") 267 } 268 .width(300).height(300) 269 .margin({left: 50}) 270 .border({width:2, color: "#6699FF"}) 271 } 272 .height('100%') 273 } 274 } 275 ``` 276  277 278## Aligning Components in Multiple Layouts 279 280You can set components in multiple layout components, such as **Row**, **Column**, **Flex**, and **Stack**, to be aligned based on the relative layout rules. 281 282 ```ts 283 @Entry 284 @Component 285 struct Index { 286 @State value: number = 0 287 build() { 288 Row() { 289 290 RelativeContainer() { 291 Row().width(100).height(100) 292 .backgroundColor('#ff33ffcc') 293 .alignRules({ 294 top: {anchor: "__container__", align: VerticalAlign.Top}, 295 left: {anchor: "__container__", align: HorizontalAlign.Start} 296 }) 297 .id("row1") 298 299 Column().width('50%').height(30).backgroundColor(0xAFEEEE) 300 .alignRules({ 301 top: {anchor: "__container__", align: VerticalAlign.Top}, 302 left: {anchor: "__container__", align: HorizontalAlign.Center} 303 }).id("row2") 304 305 Flex({ direction: FlexDirection.Row }) { 306 Text('1').width('20%').height(50).backgroundColor(0xF5DEB3) 307 Text('2').width('20%').height(50).backgroundColor(0xD2B48C) 308 Text('3').width('20%').height(50).backgroundColor(0xF5DEB3) 309 Text('4').width('20%').height(50).backgroundColor(0xD2B48C) 310 } 311 .padding(10) 312 .backgroundColor('#ffedafaf') 313 .alignRules({ 314 top: {anchor: "row2", align: VerticalAlign.Bottom}, 315 left: {anchor: "__container__", align: HorizontalAlign.Start}, 316 bottom: {anchor: "__container__", align: VerticalAlign.Center}, 317 right: {anchor: "row2", align: HorizontalAlign.Center} 318 }) 319 .id("row3") 320 321 Stack({ alignContent: Alignment.Bottom }) { 322 Text('First child, show in bottom').width('90%').height('100%').backgroundColor(0xd2cab3).align(Alignment.Top) 323 Text('Second child, show in top').width('70%').height('60%').backgroundColor(0xc1cbac).align(Alignment.Top) 324 } 325 .margin({ top: 5 }) 326 .alignRules({ 327 top: {anchor: "row3", align: VerticalAlign.Bottom}, 328 left: {anchor: "__container__", align: HorizontalAlign.Start}, 329 bottom: {anchor: "__container__", align: VerticalAlign.Bottom}, 330 right: {anchor: "row3", align: HorizontalAlign.End} 331 }) 332 .id("row4") 333 334 } 335 .width(300).height(300) 336 .margin({left: 50}) 337 .border({width:2, color: "#6699FF"}) 338 } 339 .height('100%') 340 } 341 } 342 ``` 343  344 345## Component Size 346 347The 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. 348 349 ```ts 350 @Entry 351 @Component 352 struct Index { 353 build() { 354 Row() { 355 RelativeContainer() { 356 Row(){Text('row1')}.justifyContent(FlexAlign.Center) 357 .width(100).height(100) 358 .backgroundColor("#FF3333") 359 .alignRules({ 360 top: {anchor: "__container__", align: VerticalAlign.Top}, 361 left: {anchor: "__container__", align: HorizontalAlign.Start} 362 }) 363 .id("row1") 364 365 Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100) 366 .backgroundColor("#FFCC00") 367 .alignRules({ 368 top: {anchor: "__container__", align: VerticalAlign.Top}, 369 right: {anchor: "__container__", align: HorizontalAlign.End}, 370 bottom: {anchor: "row1", align: VerticalAlign.Center}, 371 }) 372 .id("row2") 373 374 Row(){Text('row3')}.justifyContent(FlexAlign.Center).height(100) 375 .backgroundColor("#FF6633") 376 .alignRules({ 377 top: {anchor: "row1", align: VerticalAlign.Bottom}, 378 left: {anchor: "row1", align: HorizontalAlign.End}, 379 right: {anchor: "row2", align: HorizontalAlign.Start} 380 }) 381 .id("row3") 382 383 Row(){Text('row4')}.justifyContent(FlexAlign.Center) 384 .backgroundColor("#FF9966") 385 .alignRules({ 386 top: {anchor: "row3", align: VerticalAlign.Bottom}, 387 bottom: {anchor: "__container__", align: VerticalAlign.Bottom}, 388 left: {anchor: "__container__", align: HorizontalAlign.Start}, 389 right: {anchor: "row1", align: HorizontalAlign.End} 390 }) 391 .id("row4") 392 393 Row(){Text('row5')}.justifyContent(FlexAlign.Center) 394 .backgroundColor("#FF66FF") 395 .alignRules({ 396 top: {anchor: "row3", align: VerticalAlign.Bottom}, 397 bottom: {anchor: "__container__", align: VerticalAlign.Bottom}, 398 left: {anchor: "row2", align: HorizontalAlign.Start}, 399 right: {anchor: "row2", align: HorizontalAlign.End} 400 }) 401 .id("row5") 402 403 Row(){Text('row6')}.justifyContent(FlexAlign.Center) 404 .backgroundColor('#ff33ffb5') 405 .alignRules({ 406 top: {anchor: "row3", align: VerticalAlign.Bottom}, 407 bottom: {anchor: "row4", align: VerticalAlign.Bottom}, 408 left: {anchor: "row3", align: HorizontalAlign.Start}, 409 right: {anchor: "row3", align: HorizontalAlign.End} 410 }) 411 .id("row6") 412 .backgroundImagePosition(Alignment.Bottom) 413 .backgroundImageSize(ImageSize.Cover) 414 } 415 .width(300).height(300) 416 .margin({left: 50}) 417 .border({width:2, color: "#6699FF"}) 418 } 419 .height('100%') 420 } 421 } 422 ``` 423  424