Skip to content

Stack, Positioned & Sticky

A widget that positions its children relative to the edges of its box.

Basic Usage

Centered in Stack
vue
<template>
  <Container :width="200" :height="200" :decoration="lightGrayDecoration">
    <Stack>
      <Container :width="200" :height="200" :decoration="grayDecoration" />
      <Positioned :top="20" :left="20">
        <Container :width="50" :height="50" :decoration="redDecoration" />
      </Positioned>
      <Positioned :bottom="20" :right="20">
        <Container :width="50" :height="50" :decoration="blueDecoration" />
      </Positioned>
      <Center>
        <Text data="Centered in Stack" :style="whiteTextStyle" />
      </Center>
    </Stack>
  </Container>
</template>

<script setup lang="ts">
import { Container, Stack, Positioned, Center, Text, BoxDecoration, TextStyle } from "fluekit";

const lightGrayDecoration = BoxDecoration({ color: "#ddd" });
const grayDecoration = BoxDecoration({ color: "grey" });
const redDecoration = BoxDecoration({ color: "red" });
const blueDecoration = BoxDecoration({ color: "blue" });
const whiteTextStyle = TextStyle({ color: "white" });
</script>

Stack Alignment Examples

Control how non-positioned children are aligned within the stack.

alignment: topLeft
TopLeft
alignment: center
Center
alignment: bottomRight
BottomRight
vue
<template>
  <Row :gap="20">
    <Container :width="150" :height="150" :decoration="lightGrayDecoration" :padding="paddingAll10">
      <Text data="alignment: topLeft" :style="smallTextStyle" />
      <Stack alignment="topLeft" :height="120">
        <Container :width="120" :height="120" :decoration="grayDecoration" />
        <Container :width="60" :height="60" :decoration="redDecoration" alignment="center">
          <Text data="TopLeft" :style="smallWhiteTextStyle" />
        </Container>
      </Stack>
    </Container>

    <Container :width="150" :height="150" :decoration="lightGrayDecoration" :padding="paddingAll10">
      <Text data="alignment: center" :style="smallTextStyle" />
      <Stack alignment="center" :height="120">
        <Container :width="120" :height="120" :decoration="grayDecoration" />
        <Container :width="60" :height="60" :decoration="blueDecoration" alignment="center">
          <Text data="Center" :style="smallWhiteTextStyle" />
        </Container>
      </Stack>
    </Container>

    <Container :width="150" :height="150" :decoration="lightGrayDecoration" :padding="paddingAll10">
      <Text data="alignment: bottomRight" :style="smallTextStyle" />
      <Stack alignment="bottomRight" :height="120">
        <Container :width="120" :height="120" :decoration="grayDecoration" />
        <Container :width="60" :height="60" :decoration="greenDecoration" alignment="center">
          <Text data="BottomRight" :style="smallWhiteTextStyle" />
        </Container>
      </Stack>
    </Container>
  </Row>
</template>

<script setup lang="ts">
import { Container, Row, Stack, Text, BoxDecoration, TextStyle, EdgeInsets } from "fluekit";

const lightGrayDecoration = BoxDecoration({ color: "#f0f0f0" });
const grayDecoration = BoxDecoration({ color: "grey", opacity: 0.3 });
const redDecoration = BoxDecoration({ color: "red" });
const blueDecoration = BoxDecoration({ color: "blue" });
const greenDecoration = BoxDecoration({ color: "green" });

const paddingAll10 = EdgeInsets.all(10);
const smallTextStyle = TextStyle({ marginBottom: "10px", fontSize: "12px" });
const smallWhiteTextStyle = TextStyle({ color: "white", fontSize: "12px" });
</script>

Stack Fit & Mixed Children

Control how non-positioned children are sized and mix positioned and non-positioned children.

Stack with Fit Property
fit: loose
Loose
fit: expand
Expand
Mixed Positioned and Non-Positioned Children
Center
TopLeft
TopRight
BottomLeft
BottomRight
vue
<template>
  <Container :margin="EdgeInsets.only({ bottom: '20px' })">
    <Text
      data="Stack with Fit Property"
      :style="TextStyle({ marginBottom: '15px', fontSize: '16px', fontWeight: 'bold' })"
    />
    <Row :gap="20">
      <Container :width="150" :height="150" color="#f0f0f0" :padding="EdgeInsets.all(10)">
        <Text data="fit: loose" :style="TextStyle({ marginBottom: '10px', fontSize: '12px' })" />
        <Stack fit="loose" :height="120">
          <Container :width="80" :height="80" color="red" alignment="center">
            <Text data="Loose" :style="TextStyle({ color: 'white', fontSize: '12px' })" />
          </Container>
        </Stack>
      </Container>

      <Container :width="150" :height="150" color="#f0f0f0" :padding="EdgeInsets.all(10)">
        <Text data="fit: expand" :style="TextStyle({ marginBottom: '10px', fontSize: '12px' })" />
        <Stack fit="expand" :height="120">
          <Container color="blue" alignment="center">
            <Text data="Expand" :style="TextStyle({ color: 'white', fontSize: '12px' })" />
          </Container>
        </Stack>
      </Container>
    </Row>
  </Container>

  <Container>
    <Text
      data="Mixed Positioned and Non-Positioned Children"
      :style="TextStyle({ marginBottom: '15px', fontSize: '16px', fontWeight: 'bold' })"
    />
    <Container :width="350" :height="200" color="#f0f0f0" :padding="EdgeInsets.all(10)">
      <Stack :height="180" alignment="center">
        <!-- Non-positioned child (center aligned) -->
        <Container :width="150" :height="150" color="yellow" alignment="center">
          <Text data="Center" :style="TextStyle({ fontSize: '16px' })" />
        </Container>

        <!-- Positioned children -->
        <Positioned :top="20" :left="20">
          <Container :width="60" :height="60" color="red" alignment="center">
            <Text data="TopLeft" :style="TextStyle({ color: 'white', fontSize: '12px' })" />
          </Container>
        </Positioned>

        <Positioned :top="20" :right="20">
          <Container :width="60" :height="60" color="blue" alignment="center">
            <Text data="TopRight" :style="TextStyle({ color: 'white', fontSize: '12px' })" />
          </Container>
        </Positioned>

        <Positioned :bottom="20" :left="20">
          <Container :width="60" :height="60" color="green" alignment="center">
            <Text data="BottomLeft" :style="TextStyle({ color: 'white', fontSize: '12px' })" />
          </Container>
        </Positioned>

        <Positioned :bottom="20" :right="20">
          <Container :width="60" :height="60" color="purple" alignment="center">
            <Text data="BottomRight" :style="TextStyle({ color: 'white', fontSize: '12px' })" />
          </Container>
        </Positioned>
      </Stack>
    </Container>
  </Container>
</template>

<script setup lang="ts">
import { Container, Row, Stack, Positioned, Text, TextStyle, EdgeInsets } from "fluekit";
</script>

Sticky

A widget that positions its child stickily (like CSS position: sticky).

Scroll Down
Sticky Header
Item 1
Item 2
Item 3
Item 4
Sticky Bottom
Footer Area
vue
<template>
  <div class="scroll-container" style="height: 200px">
    <ScrollView>
      <Column>
        <Container :height="100" color="#e0e0e0" alignment="center">
          <Text data="Scroll Down" />
        </Container>

        <Sticky :top="0">
          <Container :height="50" color="blue" alignment="center" :width="Infinity">
            <Text
              data="Sticky Header"
              :style="TextStyle({ color: 'white', fontWeight: FontWeight.bold })"
            />
          </Container>
        </Sticky>

        <Container :height="100" color="#f0f0f0" alignment="center">
          <Text data="Item 1" />
        </Container>
        <Container :height="100" color="#e0e0e0" alignment="center">
          <Text data="Item 2" />
        </Container>
        <Container :height="100" color="#f0f0f0" alignment="center">
          <Text data="Item 3" />
        </Container>
        <Container :height="100" color="#e0e0e0" alignment="center">
          <Text data="Item 4" />
        </Container>

        <Sticky :bottom="10">
          <Container
            :height="40"
            color="red"
            alignment="center"
            :margin="EdgeInsets.only({ left: 20, right: 20 })"
            :borderRadius="20"
          >
            <Text data="Sticky Bottom" :style="TextStyle({ color: 'white' })" />
          </Container>
        </Sticky>

        <Container :height="200" color="#f8f8f8" alignment="center">
          <Text data="Footer Area" />
        </Container>
      </Column>
    </ScrollView>
  </div>
</template>

<script setup lang="ts">
import {
  Sticky,
  ScrollView,
  Column,
  Container,
  Text,
  TextStyle,
  EdgeInsets,
  FontWeight,
} from "fluekit";
</script>

<style scoped>
.scroll-container {
  border: 1px solid #ccc;
}
</style>

API

Stack

Props

NameTypeDefaultDescription
alignment'topLeft' | 'topCenter' | 'topRight' | 'centerLeft' | 'center' | 'centerRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight''topLeft'How to align the non-positioned and partially-positioned children in the stack.
clipBehavior'none' | 'hardEdge' | 'antiAlias' | 'clip''none'The content will be clipped (or not) according to this option.
textDirection'ltr' | 'rtl''ltr'The direction to use for resolving positioning.
fit'loose' | 'expand' | 'passthrough''loose'How to size the non-positioned children in the stack.

Slots

NameDescription
defaultThe children widgets.

Positioned

Props

NameTypeDefaultDescription
topnumber | string-Distance from the top.
bottomnumber | string-Distance from the bottom.
leftnumber | string-Distance from the left.
rightnumber | string-Distance from the right.
widthnumber | string-Width of the widget.
heightnumber | string-Height of the widget.

Slots

NameDescription
defaultThe child widget.

Sticky

Props

NameTypeDefaultDescription
topnumber | string-Distance from the top.
bottomnumber | string-Distance from the bottom.
leftnumber | string-Distance from the left.
rightnumber | string-Distance from the right.
widthnumber | string-Width of the widget.
heightnumber | string-Height of the widget.
zIndexnumber | string10The z-index of the widget.

Slots

NameDescription
defaultThe child widget.