1# 相对布局 (RelativeContainer) 2 3 4## 概述 5 6在应用的开发过程中,经常需要设计复杂界面,此时涉及到多个相同或不同组件之间的嵌套。如果布局组件嵌套深度过深,或者嵌套组件数过多,会带来额外的开销。如果在布局的方式上进行优化,就可以有效的提升性能,减少时间开销。<!--Del-->请参考[优化布局时间](../performance/reduce-view-nesting-levels.md#优化布局时间)了解RelativeContainer相对于List,在布局时间上的性能提升。<!--DelEnd--> 7 8RelativeContainer是一种采用相对布局的容器,支持容器内部的子元素设置相对位置关系,适用于处理界面复杂的场景,对多个子元素进行对齐和排列。子元素可以指定兄弟元素或父容器作为锚点,基于锚点进行相对位置布局。在使用锚点时,需注意子元素的相对位置关系,以避免出现错位或遮挡的情况。下图展示了一个 RelativeContainer的概念图,图中的虚线表示位置的依赖关系。 9 10 11 **图1** 相对布局示意图 12 13 14 15 16子元素并不完全是上图中的依赖关系。比如,Item4可以以Item2为依赖锚点,也可以以RelativeContainer父容器为依赖锚点。 17 18 19## 基本概念 20 21- 参考边界:设置当前组件的哪个边界对齐到锚点。 22 23- 锚点:通过锚点设置当前元素基于哪个元素确定位置。 24 25- 对齐方式:通过对齐方式,设置当前元素是基于锚点的上中下对齐,还是基于锚点的左中右对齐。 26 27 28## 设置依赖关系 29 30### 设置参考边界 31 32设置当前组件的哪个边界对齐到锚点。容器内子组件的参考边界区分水平方向和垂直方向。 33* 在水平方向上,可以按照起始(left)、居中(middle)或尾端(right)的组件边界与锚点对齐。当设置三个边界时,仅起始(left)和居中(middle)的边界设置生效。 34 35* 在垂直方向上,可以设置组件边界与锚点对齐,具体包括顶部(top)、居中(center)和底部(bottom)。当设置三个边界时,仅顶部(top)和居中(center)生效。 36 37 38### 设置锚点 39 40锚点设置涉及子元素相对于其父元素或兄弟元素的位置依赖关系。具体而言,子元素可以将其位置锚定到相对布局容器(RelativeContainer)、辅助线(guideline)、屏障(barrier)或其他子元素上。 41 42为了准确定义锚点,RelativeContainer的子元素必须拥有唯一的组件标识(id),用于指定锚点信息。父元素RelativeContainer的标识默认为“\_\_container\_\_”,其他子元素的组件标识(id)则通过[id](../reference/apis-arkui/arkui-ts/ts-universal-attributes-component-id.md#id)属性设置。 43 44> **说明:** 45> 46> * 未设置组件标识(id)的组件虽可显示,但无法被其他组件引用为锚点。相对布局容器会为其拼接组件标识,但组件标识(id)的规律无法被应用感知。辅助线(guideline)与屏障(barrier)的组件标识(id)需确保唯一,避免与任何组件冲突。若有重复,遵循组件 > guideline > barrier 的优先级。 47> * 组件间设置锚点时应避免形成依赖循环(组件之间设置链除外),依赖循环将导致子组件缺乏定位基准,最终无法绘制。 48 49- RelativeContainer父组件为锚点,__container__代表父容器的组件标识(id)。 50 51 ```ts 52 let AlignRus: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = { 53 'top': { 'anchor': '__container__', 'align': VerticalAlign.Top }, 54 'left': { 'anchor': '__container__', 'align': HorizontalAlign.Start } 55 } 56 let AlignRue: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = { 57 'top': { 'anchor': '__container__', 'align': VerticalAlign.Top }, 58 'right': { 'anchor': '__container__', 'align': HorizontalAlign.End } 59 } 60 let Mleft: Record<string, number> = { 'left': 20 } 61 let BWC: Record<string, number | string> = { 'width': 2, 'color': '#6699FF' } 62 63 @Entry 64 @Component 65 struct Index { 66 build() { 67 RelativeContainer() { 68 Row() { 69 Text('row1') 70 } 71 .justifyContent(FlexAlign.Center) 72 .width(100) 73 .height(100) 74 .backgroundColor('#a3cf62') 75 .alignRules(AlignRus) 76 .id("row1") 77 78 Row() { 79 Text('row2') 80 } 81 .justifyContent(FlexAlign.Center) 82 .width(100) 83 .height(100) 84 .backgroundColor('#00ae9d') 85 .alignRules(AlignRue) 86 .id("row2") 87 }.width(300).height(300) 88 .margin(Mleft) 89 .border(BWC) 90 } 91 } 92 ``` 93 94  95 96- 以兄弟元素为锚点。 97 98 ```ts 99 let AlignRus: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = { 100 'top': { 'anchor': '__container__', 'align': VerticalAlign.Top }, 101 'left': { 'anchor': '__container__', 'align': HorizontalAlign.Start } 102 } 103 let RelConB: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = { 104 'top': { 'anchor': 'row1', 'align': VerticalAlign.Bottom }, 105 'left': { 'anchor': 'row1', 'align': HorizontalAlign.Start } 106 } 107 let Mleft: Record<string, number> = { 'left': 20 } 108 let BWC: Record<string, number | string> = { 'width': 2, 'color': '#6699FF' } 109 110 @Entry 111 @Component 112 struct Index { 113 build() { 114 RelativeContainer() { 115 Row() { 116 Text('row1') 117 } 118 .justifyContent(FlexAlign.Center) 119 .width(100) 120 .height(100) 121 .backgroundColor('#00ae9d') 122 .alignRules(AlignRus) 123 .id("row1") 124 125 Row() { 126 Text('row2') 127 } 128 .justifyContent(FlexAlign.Center) 129 .width(100) 130 .height(100) 131 .backgroundColor('#a3cf62') 132 .alignRules(RelConB) 133 .id("row2") 134 }.width(300).height(300) 135 .margin(Mleft) 136 .border(BWC) 137 } 138 } 139 ``` 140 141  142 143- 子组件锚点可以任意选择,但需注意不要相互依赖。 144 145 ```ts 146 @Entry 147 @Component 148 struct Index { 149 build() { 150 Row() { 151 RelativeContainer() { 152 Row(){Text('row1')}.justifyContent(FlexAlign.Center).width(100).height(100) 153 .backgroundColor('#a3cf62') 154 .alignRules({ 155 top: {anchor: "__container__", align: VerticalAlign.Top}, 156 left: {anchor: "__container__", align: HorizontalAlign.Start} 157 }) 158 .id("row1") 159 160 Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100) 161 .backgroundColor('#00ae9d') 162 .alignRules({ 163 top: {anchor: "__container__", align: VerticalAlign.Top}, 164 right: {anchor: "__container__", align: HorizontalAlign.End}, 165 bottom: {anchor: "row1", align: VerticalAlign.Center}, 166 }) 167 .id("row2") 168 169 Row(){Text('row3')}.justifyContent(FlexAlign.Center).height(100) 170 .backgroundColor('#0a59f7') 171 .alignRules({ 172 top: {anchor: "row1", align: VerticalAlign.Bottom}, 173 left: {anchor: "row1", align: HorizontalAlign.Start}, 174 right: {anchor: "row2", align: HorizontalAlign.Start} 175 }) 176 .id("row3") 177 178 Row(){Text('row4')}.justifyContent(FlexAlign.Center) 179 .backgroundColor('#2ca9e0') 180 .alignRules({ 181 top: {anchor: "row3", align: VerticalAlign.Bottom}, 182 left: {anchor: "row1", align: HorizontalAlign.Center}, 183 right: {anchor: "row2", align: HorizontalAlign.End}, 184 bottom: {anchor: "__container__", align: VerticalAlign.Bottom} 185 }) 186 .id("row4") 187 } 188 .width(300).height(300) 189 .margin({left: 50}) 190 .border({width:2, color: "#6699FF"}) 191 } 192 .height('100%') 193 } 194 } 195 ``` 196  197 198### 设置相对于锚点的对齐位置 199 200设置了锚点之后,可以通过[alignRules](../reference/apis-arkui/arkui-ts/ts-universal-attributes-location.md#alignrules9)属性的align设置相对于锚点的对齐位置。 201 202在水平方向上,对齐位置可以设置为HorizontalAlign.Start、HorizontalAlign.Center、HorizontalAlign.End。 203 204 205 206在竖直方向上,对齐位置可以设置为VerticalAlign.Top、VerticalAlign.Center、VerticalAlign.Bottom。 207 208 209 210### 子组件位置偏移 211 212子组件经过相对位置对齐后,可能尚未达到目标位置。开发者可根据需要设置额外偏移(offset)。当使用offset调整位置的组件作为锚点时,对齐位置为设置offset之前的位置。从API Version 11开始,新增了[bias](../reference/apis-arkui/arkui-ts/ts-universal-attributes-location.md#bias对象说明)对象,建议API Version 11及以后的版本使用bias来设置额外偏移。 213 214 ```ts 215@Entry 216@Component 217struct Index { 218 build() { 219 Row() { 220 RelativeContainer() { 221 Row() { 222 Text('row1') 223 } 224 .justifyContent(FlexAlign.Center) 225 .width(100) 226 .height(100) 227 .backgroundColor('#a3cf62') 228 .alignRules({ 229 top: { anchor: "__container__", align: VerticalAlign.Top }, 230 left: { anchor: "__container__", align: HorizontalAlign.Start } 231 }) 232 .id("row1") 233 234 Row() { 235 Text('row2') 236 } 237 .justifyContent(FlexAlign.Center) 238 .width(100) 239 .backgroundColor('#00ae9d') 240 .alignRules({ 241 top: { anchor: "__container__", align: VerticalAlign.Top }, 242 right: { anchor: "__container__", align: HorizontalAlign.End }, 243 bottom: { anchor: "row1", align: VerticalAlign.Center }, 244 }) 245 .offset({ 246 x: -40, 247 y: -20 248 }) 249 .id("row2") 250 251 Row() { 252 Text('row3') 253 } 254 .justifyContent(FlexAlign.Center) 255 .height(100) 256 .backgroundColor('#0a59f7') 257 .alignRules({ 258 top: { anchor: "row1", align: VerticalAlign.Bottom }, 259 left: { anchor: "row1", align: HorizontalAlign.End }, 260 right: { anchor: "row2", align: HorizontalAlign.Start } 261 }) 262 .offset({ 263 x: -10, 264 y: -20 265 }) 266 .id("row3") 267 268 Row() { 269 Text('row4') 270 } 271 .justifyContent(FlexAlign.Center) 272 .backgroundColor('#2ca9e0') 273 .alignRules({ 274 top: { anchor: "row3", align: VerticalAlign.Bottom }, 275 bottom: { anchor: "__container__", align: VerticalAlign.Bottom }, 276 left: { anchor: "__container__", align: HorizontalAlign.Start }, 277 right: { anchor: "row1", align: HorizontalAlign.End } 278 }) 279 .offset({ 280 x: -10, 281 y: -30 282 }) 283 .id("row4") 284 285 Row() { 286 Text('row5') 287 } 288 .justifyContent(FlexAlign.Center) 289 .backgroundColor('#30c9f7') 290 .alignRules({ 291 top: { anchor: "row3", align: VerticalAlign.Bottom }, 292 bottom: { anchor: "__container__", align: VerticalAlign.Bottom }, 293 left: { anchor: "row2", align: HorizontalAlign.Start }, 294 right: { anchor: "row2", align: HorizontalAlign.End } 295 }) 296 .offset({ 297 x: 10, 298 y: 20 299 }) 300 .id("row5") 301 302 Row() { 303 Text('row6') 304 } 305 .justifyContent(FlexAlign.Center) 306 .backgroundColor('#ff33ffb5') 307 .alignRules({ 308 top: { anchor: "row3", align: VerticalAlign.Bottom }, 309 bottom: { anchor: "row4", align: VerticalAlign.Bottom }, 310 left: { anchor: "row3", align: HorizontalAlign.Start }, 311 right: { anchor: "row3", align: HorizontalAlign.End } 312 }) 313 .offset({ 314 x: -15, 315 y: 10 316 }) 317 .backgroundImagePosition(Alignment.Bottom) 318 .backgroundImageSize(ImageSize.Cover) 319 .id("row6") 320 } 321 .width(300).height(300) 322 .margin({ left: 50 }) 323 .border({ width: 2, color: "#6699FF" }) 324 } 325 .height('100%') 326 } 327} 328 ``` 329  330 331## 多种组件的对齐布局 332 333Row、Column、Flex、Stack等多种布局组件,可按照RelativeContainer组件规则进行对齐排布。 334 335 ```ts 336@Entry 337@Component 338struct Index { 339 @State value: number = 0 340 341 build() { 342 Row() { 343 344 RelativeContainer() { 345 Row() 346 .width(100) 347 .height(100) 348 .backgroundColor('#a3cf62') 349 .alignRules({ 350 top: { anchor: "__container__", align: VerticalAlign.Top }, 351 left: { anchor: "__container__", align: HorizontalAlign.Start } 352 }) 353 .id("row1") 354 355 Column() 356 .width('50%') 357 .height(30) 358 .backgroundColor('#00ae9d') 359 .alignRules({ 360 top: { anchor: "__container__", align: VerticalAlign.Top }, 361 left: { anchor: "__container__", align: HorizontalAlign.Center } 362 }) 363 .id("row2") 364 365 Flex({ direction: FlexDirection.Row }) { 366 Text('1').width('20%').height(50).backgroundColor('#0a59f7') 367 Text('2').width('20%').height(50).backgroundColor('#2ca9e0') 368 Text('3').width('20%').height(50).backgroundColor('#0a59f7') 369 Text('4').width('20%').height(50).backgroundColor('#2ca9e0') 370 } 371 .padding(10) 372 .backgroundColor('#30c9f7') 373 .alignRules({ 374 top: { anchor: "row2", align: VerticalAlign.Bottom }, 375 left: { anchor: "__container__", align: HorizontalAlign.Start }, 376 bottom: { anchor: "__container__", align: VerticalAlign.Center }, 377 right: { anchor: "row2", align: HorizontalAlign.Center } 378 }) 379 .id("row3") 380 381 Stack({ alignContent: Alignment.Bottom }) { 382 Text('First child, show in bottom').width('90%').height('100%').backgroundColor('#a3cf62').align(Alignment.Top) 383 Text('Second child, show in top').width('70%').height('60%').backgroundColor('#00ae9d').align(Alignment.Top) 384 } 385 .margin({ top: 5 }) 386 .alignRules({ 387 top: { anchor: "row3", align: VerticalAlign.Bottom }, 388 left: { anchor: "__container__", align: HorizontalAlign.Start }, 389 bottom: { anchor: "__container__", align: VerticalAlign.Bottom }, 390 right: { anchor: "row3", align: HorizontalAlign.End } 391 }) 392 .id("row4") 393 394 } 395 .width(300).height(300) 396 .margin({ left: 50 }) 397 .border({ width: 2, color: "#6699FF" }) 398 } 399 .height('100%') 400 } 401} 402 ``` 403  404 405## 组件尺寸 406 407当同时存在前端页面设置的子组件尺寸和相对布局规则时,子组件的绘制尺寸依据约束规则确定。从API Version 11开始,此规则有所变化,子组件自身设置的尺寸优先级高于相对布局规则中的对齐锚点尺寸。因此,若要使子组件与锚点严格对齐,应仅使用alignRules,避免使用[尺寸设置](../reference/apis-arkui/arkui-ts/ts-universal-attributes-size.md#尺寸设置)。 408 409> **说明:** 410> 411> * 根据约束条件和子组件自身的size属性无法确定子组件的大小,此时,不绘制该子组件。 412> * 在同一方向上设置两个或更多锚点时,若这些锚点的位置顺序有误,该子组件将被视为大小为0而不予绘制。 413```ts 414@Entry 415@Component 416struct Index { 417 build() { 418 Row() { 419 RelativeContainer() { 420 Row() { 421 Text('row1') 422 } 423 .justifyContent(FlexAlign.Center) 424 .width(100) 425 .height(100) 426 .backgroundColor('#a3cf62') 427 .alignRules({ 428 top: { anchor: "__container__", align: VerticalAlign.Top }, 429 left: { anchor: "__container__", align: HorizontalAlign.Start } 430 }) 431 .id("row1") 432 433 Row() { 434 Text('row2') 435 } 436 .justifyContent(FlexAlign.Center) 437 .width(100) 438 .backgroundColor('#00ae9d') 439 .alignRules({ 440 top: { anchor: "__container__", align: VerticalAlign.Top }, 441 right: { anchor: "__container__", align: HorizontalAlign.End }, 442 bottom: { anchor: "row1", align: VerticalAlign.Center }, 443 }) 444 .id("row2") 445 446 Row() { 447 Text('row3') 448 } 449 .justifyContent(FlexAlign.Center) 450 .height(100) 451 .backgroundColor('#0a59f7') 452 .alignRules({ 453 top: { anchor: "row1", align: VerticalAlign.Bottom }, 454 left: { anchor: "row1", align: HorizontalAlign.End }, 455 right: { anchor: "row2", align: HorizontalAlign.Start } 456 }) 457 .id("row3") 458 459 Row() { 460 Text('row4') 461 }.justifyContent(FlexAlign.Center) 462 .backgroundColor('#2ca9e0') 463 .alignRules({ 464 top: { anchor: "row3", align: VerticalAlign.Bottom }, 465 bottom: { anchor: "__container__", align: VerticalAlign.Bottom }, 466 left: { anchor: "__container__", align: HorizontalAlign.Start }, 467 right: { anchor: "row1", align: HorizontalAlign.End } 468 }) 469 .id("row4") 470 471 Row() { 472 Text('row5') 473 }.justifyContent(FlexAlign.Center) 474 .backgroundColor('#30c9f7') 475 .alignRules({ 476 top: { anchor: "row3", align: VerticalAlign.Bottom }, 477 bottom: { anchor: "__container__", align: VerticalAlign.Bottom }, 478 left: { anchor: "row2", align: HorizontalAlign.Start }, 479 right: { anchor: "row2", align: HorizontalAlign.End } 480 }) 481 .id("row5") 482 483 Row() { 484 Text('row6') 485 } 486 .justifyContent(FlexAlign.Center) 487 .backgroundColor('#ff33ffb5') 488 .alignRules({ 489 top: { anchor: "row3", align: VerticalAlign.Bottom }, 490 bottom: { anchor: "row4", align: VerticalAlign.Bottom }, 491 left: { anchor: "row3", align: HorizontalAlign.Start }, 492 right: { anchor: "row3", align: HorizontalAlign.End } 493 }) 494 .id("row6") 495 .backgroundImagePosition(Alignment.Bottom) 496 .backgroundImageSize(ImageSize.Cover) 497 } 498 .width(300).height(300) 499 .margin({ left: 50 }) 500 .border({ width: 2, color: "#6699FF" }) 501 } 502 .height('100%') 503 } 504} 505``` 506  507 508 509## 多个组件形成链 510 511链的形成依赖于组件之间的关联关系。以组件A和组件B构成的最简水平链为例,其依赖关系为:锚点1 <-- 组件A <---> 组件B --> 锚点2,即A具有left锚点,B具有right锚点,同时A的right锚点与B的HorizontalAlign.Start对齐,B的left锚点与A的HorizontalAlign.End对齐。 512* 链的方向和格式在链头组件的[chainMode](../reference/apis-arkui/arkui-ts/ts-universal-attributes-location.md#chainmode12)接口中声明;链内元素的bias属性全部失效,链头元素的bias属性作为整个链的bias生效。链头是指在满足成链规则时链的第一个组件(在水平方向上,从左边开始,镜像语言中从右边开始;在竖直方向上,从上边开始)。 513* 如果链内所有元素的size超出链的锚点约束,超出部分将被均匀分配到链的两侧。在[Packed](../reference/apis-arkui/arkui-ts/ts-universal-attributes-location.md#chainstyle12)链中,可以通过[bias](../reference/apis-arkui/arkui-ts/ts-universal-attributes-location.md#bias对象说明)设置超出部分的分布。 514 515 516```ts 517@Entry 518@Component 519struct Index { 520 build() { 521 Row() { 522 RelativeContainer() { 523 Row() { 524 Text('row1') 525 } 526 .justifyContent(FlexAlign.Center) 527 .width(80) 528 .height(80) 529 .backgroundColor('#a3cf62') 530 .alignRules({ 531 left: { anchor: "__container__", align: HorizontalAlign.Start }, 532 right: { anchor: "row2", align: HorizontalAlign.Start }, 533 top: { anchor: "__container__", align: VerticalAlign.Top } 534 }) 535 .id("row1") 536 .chainMode(Axis.Horizontal, ChainStyle.SPREAD) 537 538 Row() { 539 Text('row2') 540 } 541 .justifyContent(FlexAlign.Center) 542 .width(80) 543 .height(80) 544 .backgroundColor('#00ae9d') 545 .alignRules({ 546 left: { anchor: "row1", align: HorizontalAlign.End }, 547 right: { anchor: "row3", align: HorizontalAlign.Start }, 548 top: { anchor: "row1", align: VerticalAlign.Top } 549 }) 550 .id("row2") 551 552 Row() { 553 Text('row3') 554 } 555 .justifyContent(FlexAlign.Center) 556 .width(80) 557 .height(80) 558 .backgroundColor('#0a59f7') 559 .alignRules({ 560 left: { anchor: "row2", align: HorizontalAlign.End }, 561 right: { anchor: "__container__", align: HorizontalAlign.End }, 562 top: { anchor: "row1", align: VerticalAlign.Top } 563 }) 564 .id("row3") 565 566 Row() { 567 Text('row4') 568 } 569 .justifyContent(FlexAlign.Center) 570 .width(80) 571 .height(80) 572 .backgroundColor('#a3cf62') 573 .alignRules({ 574 left: { anchor: "__container__", align: HorizontalAlign.Start }, 575 right: { anchor: "row5", align: HorizontalAlign.Start }, 576 center: { anchor: "__container__", align: VerticalAlign.Center } 577 }) 578 .id("row4") 579 .chainMode(Axis.Horizontal, ChainStyle.SPREAD_INSIDE) 580 581 Row() { 582 Text('row5') 583 } 584 .justifyContent(FlexAlign.Center) 585 .width(80) 586 .height(80) 587 .backgroundColor('#00ae9d') 588 .alignRules({ 589 left: { anchor: "row4", align: HorizontalAlign.End }, 590 right: { anchor: "row6", align: HorizontalAlign.Start }, 591 top: { anchor: "row4", align: VerticalAlign.Top } 592 }) 593 .id("row5") 594 595 Row() { 596 Text('row6') 597 } 598 .justifyContent(FlexAlign.Center) 599 .width(80) 600 .height(80) 601 .backgroundColor('#0a59f7') 602 .alignRules({ 603 left: { anchor: "row5", align: HorizontalAlign.End }, 604 right: { anchor: "__container__", align: HorizontalAlign.End }, 605 top: { anchor: "row4", align: VerticalAlign.Top } 606 }) 607 .id("row6") 608 609 Row() { 610 Text('row7') 611 } 612 .justifyContent(FlexAlign.Center) 613 .width(80) 614 .height(80) 615 .backgroundColor('#a3cf62') 616 .alignRules({ 617 left: { anchor: "__container__", align: HorizontalAlign.Start }, 618 right: { anchor: "row8", align: HorizontalAlign.Start }, 619 bottom: { anchor: "__container__", align: VerticalAlign.Bottom } 620 }) 621 .id("row7") 622 .chainMode(Axis.Horizontal, ChainStyle.PACKED) 623 624 Row() { 625 Text('row8') 626 } 627 .justifyContent(FlexAlign.Center) 628 .width(80) 629 .height(80) 630 .backgroundColor('#00ae9d') 631 .alignRules({ 632 left: { anchor: "row7", align: HorizontalAlign.End }, 633 right: { anchor: "row9", align: HorizontalAlign.Start }, 634 top: { anchor: "row7", align: VerticalAlign.Top } 635 }) 636 .id("row8") 637 638 Row() { 639 Text('row9') 640 } 641 .justifyContent(FlexAlign.Center) 642 .width(80) 643 .height(80) 644 .backgroundColor('#0a59f7') 645 .alignRules({ 646 left: { anchor: "row8", align: HorizontalAlign.End }, 647 right: { anchor: "__container__", align: HorizontalAlign.End }, 648 top: { anchor: "row7", align: VerticalAlign.Top } 649 }) 650 .id("row9") 651 } 652 .width(300).height(300) 653 .margin({ left: 50 }) 654 .border({ width: 2, color: "#6699FF" }) 655 } 656 .height('100%') 657 } 658} 659``` 660