Help Aligning component in Expandable Card Header & Keeping It Visible in Expanded View

Hi OpenHAB Community,

I’m working on a custom widget using an expandable f7-card component and having a bit of trouble with aligning an oh-button within the card header. Currently, I have the oh-button in the right-hand corner of the header, but I’d like it to stay visible and aligned even after the card expands. Right now, the button either shifts out of view or disappears entirely when the card is expanded.

Here’s the relevant part of my code:

uid: widget_templateexpandable
tags: []
props:
  parameters:
    - description: A text prop
      label: Prop 1
      name: prop1
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Nov 14, 2024, 4:35:48 PM
component: f7-card
config:
  outline: true
  padding: true
  expandable: true
  style:
    --f7-card-expandable-tablet-height: 75vh
    --f7-card-expandable-tablet-width: 35vw
    background-color: "=props.bgcolor ? props.bgcolor : ''"
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
    height: 150px
    margin-left: 5px
    margin-right: 5px
    margin-top: 10px
    noShadow: false
    padding: 0px
  swipeToClose: true
slots:
  default:
    - component: f7-row
      config:
        class:
          - align-items-center
          - justify-content-space-between
        style:
          font-weight: bold
          font-size: 18px
          background-color: "#f0f0f0"
          height: 20px
      slots:
        default:
          - component: f7-col
            config:
              style:
                background-color: "green"
                text-align: center
                width: 90%
            slots:
              default:
                - component: Label
                  config:
                    text: Card Header
          - component: f7-col
            config:
              style:
                text-align: right
                width: 10%
            slots:
              default:
                - component: oh-button
                  config:
                    class:
                      - cell-open-button
                      - card-opened-fade-out
                    color: black
                    iconF7: expand
                    iconSize: 30px
                    style:
                      padding-bottom: 35px
                      
    - component: f7-row
      config:
        class:
          - justify-content-center
        style:
          font-size: 16px
          height: 110px
      slots:
        default:
          - component: Label
            config:
              text

I’d like the oh-button to:

  1. Stay aligned on the right side of the header.
  2. Remain visible after the card expands, instead of disappearing or shifting out of view.
    Bildschirmfoto vom 2024-11-14 16-55-46

    3.If i change the code to a better column ratio why is the oh-button than in the next row?
- component: f7-row
      config:
        class:
          - align-items-center
          - justify-content-space-between
        style:
          font-weight: bold
          font-size: 18px
          background-color: "#f0f0f0"
          height: 20px
          margin: 0 0 0 0
          width: 100%
      slots:
        default:
          - component: f7-col
            config:
              style:
                background-color: green
                text-align: center
                width: 80%
            slots:
              default:
                - component: Label
                  config:
                    text: Card Header
          - component: f7-col
            config:
              style:
                text-align: right
            slots:
              default:
                - component: oh-button
                  config:
                    class:
                      - cell-open-button
                      - card-opened-fade-out
                    color: black
                    iconF7: expand
                    iconSize: 0px
                    style:
                      width: 20%
                      background-color: green

Bildschirmfoto vom 2024-11-14 17-19-56

If anyone has encountered this issue or has any tips for getting the button to stay visible in the expanded view, I’d really appreciate the help! Thanks!

The button disappears because you have given it the card-opened-fade-out class.

As for the alignment, by default, the f7-row is using display: flex. That makes keeping all of the child items on one row very simple, you just have to add flex-wrap: nowrap to the row’s styles.

On a more fundamental level, I suspect that one of the reason the elements are not staying on the same row to begin with is the additional f7-col components. I wouldn’t bother to include those myself. Those are most helpful when you have more than one row and you are trying to coordinate the columns between those row to get a grid appearance. Here you just have the one row, so let flexbox do it’s job and if you need more precise control over the size or position of the row’s child elements, then give the elements individual flex properties (for example, you don’t really want the button to grow or shrink so something like flex: 0 0 10% will make the button always 10% of the row with now reactive growth or shrinkage).

I’m working further on the layout using the following YAML configuration, and I noticed that the f7-block component has a gap between its top and the elements above it. Despite setting margin: 0 and padding: 0 in the relevant style sections, there’s still an unexplained space between the f7-block and the previous row or component.

Here’s a snippet of the YAML for the section in question:

uid: Cell_Wallplugnew
tags: []
props:
  parameters:
    - context: item
      description: A actual power item to display
      label: Item
      name: itemActualPower
      required: false
      type: TEXT
    - context: item
      description: A total power item to display
      label: Item
      name: itemTotalePower
      required: false
      type: TEXT
    - context: item
      description: A daily total power item to display
      label: Item
      name: itemDailyTotalPower
      required: false
      type: TEXT
    - context: item
      description: the switch state
      label: Item
      name: itemSwitch
      required: false
      type: TEXT
    - description: URL to show in the frame
      label: Source URL
      name: URL
      required: true
      type: TEXT
    - default: from=now-6h&to=now;6h,from=now-12h&to=now;12h,from=now-1d&to=now;24h,from=now/d&to=now/d;Day,from=now-3d&to=now;Last
        3 Days,from=now-7d&to=now;Last 7 Days,from=now-14d&to=now;Last 14 Days
      description: Comma-separated List of options. Example
        "from=now-6h&to=now;-6h,from=now-1d/d&to=now-1d/d;yesterday" for past
        "6h" and "yesterday". First entry is default.
      label: Time range options
      name: timerange
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Nov 16, 2024, 12:46:50 PM
component: f7-card
config:
  expandable: true
  style:
    --f7-card-expandable-tablet-height: 75vh
    --f7-card-expandable-tablet-width: 35vw
    background-color: "=props.bgcolor ? props.bgcolor : ''"
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
    height: 150px
    margin-left: 5px
    margin-right: 5px
    margin-top: 10px
    noShadow: false
    padding: 0px
  swipeToClose: true
slots:
  default:
    - component: f7-row
      config:
        class:
          - align-items-center
          - justify-content-space-between
        style:
          background-color: "#f0f0f0"
          font-size: 18px
          font-weight: bold
          height: 20px
          margin: 0 0 0 0
          width: 100%
          flex-wrap: nowrap
      slots:
        default:
          - component: f7-col
            config:
              style:
                background-color: green
                text-align: center
                width: 80%
            slots:
              default:
                - component: Label
                  config:
                    text: Card Header
          - component: f7-col
            config:
              style:
                width: 20%
            slots:
              default:
                - component: oh-button
                  config:
                    class:
                      - cell-open-button
                      - card-opened-fade-out
                      - card-open
                    color: black
                    iconF7: expand
                    iconSize: 20px
                    style:
                      background-color: green
                      text-align: right
    - component: f7-card-content
      config:
        style:
          width: 100%
          background-color: yellow
          margin: 0 0 0 0
          padding: 0 0 0 0
      slots:
        default:
          - component: f7-row
            config:
              class:
                - align-items-center
              style:
                background-color: "#f0f0f0"
                font-size: 18px
                font-weight: bold
                height: 20px
                margin: 0 0 0 0
                width: 100%
                flex-wrap: nowrap
            slots:
              default:
                - component: f7-col
                  config:
                    style:
                      background-color: green
                      text-align: center
                      width: 80%
                  slots:
                    default:
                      - component: Label
                        config:
                          text: Card Header
                - component: f7-col
                  config:
                    style:
                      width: 20%
                  slots:
                    default:
                      - component: oh-button
                        config:
                          class:
                            #- cell-open-button
                            #- card-opened-fade-out
                            #- card-open
                          color: black
                          iconF7: expand
                          iconSize: 20px
                          style:
                            background-color: green
                            text-align: right
          - component: f7-row
            config:
              class:
                - justify-content-center
              style:
                font-size: 16px
                margin: 0 0 0 0
                padding: 0 0 0 0
            slots: 
              default:
              - component: f7-block
                config:
                  class:
                    - card-prevent-open
                    - card-content-padding
                  outline: false
                  style:
                    width: 100%
                    height: 115px
                    background-color: red
                slots:
                  default:
                    - component: f7-list
                      config: {}
                      slots:
                        default:
                          - component: oh-toggle-item
              - component: f7-block
                config:
                  class:
                    - card-prevent-open
                    - card-content-padding
                  outline: false
                  style:
                    width: 100%
                slots:
                  default:
                    - component: f7-list
                      config: {}
                      slots:
                        default:
                          - component: oh-toggle-item
                            config:
                              color: green
                              icon: oh:poweroutlet
                              item: =props.itemSwitch
                              title: Steckdose
                          - component: oh-label-item
                            config:
                              color: blue
                              icon: f7:chart_bar_circle
                              item: =props.itemDailyTotalPower
                              title: Daily Totayl Power
                          - component: oh-label-item
                            config:
                              color: blue
                              icon: f7:chart_bar
                              item: =props.itemActualPower
                              title: Actual Power
                          - component: oh-label-item
                            config:
                              color: blue
                              icon: f7:chart_bar_square_fill
                              item: =props.itemTotalePower
                              title: Totale Power
                    - component: oh-webframe-card
                      config:
                        borders: false
                        class:
                          - display-block
                        height: 240px
                        noBorder: false
                        noShadow: true
                        src: =props.URL.replace('{period}', vars.selectedPeriod ||
                          [props.timerange.split(',')[0].split(';')[0]])
                    - component: f7-segmented
                      config:
                        class:
                          - padding-bottom-half
                        outline: false
                        round: false
                        style:
                          --f7-button-border-radius: 4px
                          --f7-button-font-size: 14px
                          --f7-button-font-weight: 300
                          --f7-button-outline-border-width: 1px
                          --f7-button-padding-horizontal: 0px
                          --f7-button-padding-vertical: 0px
                          --f7-button-text-color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
                          --f7-button-text-transform: none
                          margin-left: 10px
                          margin-right: 10px
                          margin-top: 250px
                      slots:
                        default:
                          - component: oh-repeater
                            config:
                              for: size
                              fragment: true
                              sourceType: range
                            slots:
                              default:
                                - component: oh-repeater
                                  config:
                                    for: period
                                    fragment: true
                                    in: =[props.timerange.split(",")[loop.size].split(";")[1]]
                                  slots:
                                    default:
                                      - component: oh-button
                                        config:
                                          action: variable
                                          actionVariable: selectedPeriod
                                          actionVariableValue: =props.timerange.split(",")[loop.size].split(";")[0]
                                          fill: "=(([props.timerange.split(',')[loop.size].split(';')[0]] ==
                                            vars.selectedPeriod) ||
                                            (props.timerange.split(',')[0].split(';\
                                            ')[1] === loop.period) &&
                                            !vars.selectedPeriod) ? true : false"
                                          outline: true
                                          round: false
                                          style:
                                            --f7-button-border-color: var(--f7-card-outline-border-color)
                                          text: =loop.period

Despite my best efforts with CSS styles like margin: 0, padding: 0, and even tweaking height, the block is not aligning snugly to the top of the parent container.

I’d appreciate any suggestions or insights on:

  1. Possible hidden margins/padding applied by f7-block or parent components.
  2. Debugging tips to identify where the extra spacing originates.

Thank you in advance for your help!

Yep, that’s the trade-off with using all the f7 components. There’s a lot of styling under-the-hood which means that you have to do less most of the time, but when you have something specific in mind you have to sort through all the extra.

In this case the margin is on the block itself.

All I ever use when I can’t work out css issues is the elements tab in the browser console. I start with the element that looks like it is having the problem and then work my way up the tree. In this case you don’t have to go far. Inspecting the block itself you see:

image

Which shows you that there in, in fact, some directive setting a 16 pixel top margin. So looking in the full styles list it is easy to find:

image

Now we know that because this element is 1) on a page, and 2) an f7-block that is the first child of it’s parent it gets a top margin value. So, margin: 0 or margin-top: 0 on the block itself will remove the gap at the top.