[OH4] Widget height by number of columns

Hi,
I try to setup the overview page in a way that I can use it for smartphone (portrait) and tablet (landscape). Therefore I proceeded a lot already by reading the community contributions already.
Something I try to handle: Set the widget height depending on the number of columns, fallback would be screen width. I could not find a way of doing so.
My workaround that I do not like as it just works as the tablet app is using webview:

    height: "=device.desktop ? '180px' : device.ios ? '140px' : device.android ? '140px' : device.webView ? '180px' : '140px'"

Any better idea?

I try to embedded this into this page layout: On a smartphone I have all the widgets with minimum height below each other while on a tablet I can arrange a pre-defined, fixed size:

config:
  label: OverviewTest2
  sidebar: true
blocks: []
masonry:
  - component: oh-masonry
    config:
      cols:
        "768": 1
        "1023": 1
        "1280": 1
        default: 3
    slots:
      default:
        - component: f7-col
          slots:
            default:
              - component: widget:Cell_Notification
                config: {}
              - component: widget:Cell_People
                config: {}
              - component: widget:Cell_House
                config: {}
        - component: f7-col
          slots:
            default:
              - component: widget:Cell_Energy
                config: {}
        - component: f7-col
          slots:
            default:
              - component: widget:Cell_Weather_Actual
                config: {}
              - component: widget:Cell_Astro
                config: {}
grid: []
canvas: []

Thanks!

The way to handle this is though the column options. Click on the column config and choose Column Options.

There you can specify what percentage of the row the column takes up based on the width of the display.

In this example, on any screen less that 1024 pixels wide this column takes up the full row and it takes up 1/3rd of the row for bigger screens. The other columns on the row get moved to the next row.

Thus, on my phone I end up with one column with one widget per row and on wide screens I have one row with three widgets across.

Hi,

I know this and have a working solutions for the rows. What I want to achieve is the widget HEIGHT dependent on the NUMBER of rows. Slightly different :wink:

Best
Matthias

There is no built-in configuration for this, widget heights are mostly independent of screen size.

The work-around that you’ve shown is one perfectly good way of making this happen.

One other option I’ve never tried (but should work) would be to use a media query in a stylesheet to override the height of any widget that you have assigned a specific class. Then it could match your cols definitions. For example:

stylesheet: >
  @media screen and (max-width: 768px) {
    .mobile-height {
      height: 180px;
    }
  }

Will use that height declaration on any widget with the mobile-height class whenever the screen is 768 pixels wide or less.

Interesting approach!
I am just not sure where and how to place it. Do you have a hint?

Is there any variable telling me the width of the screen? I could not find anything but this would be quite reliable for my logic instead of the work around.

Thanks and best

The stylesheet property can be added to the config section of most pages and components. In this case, if you have many widgets on one page that you want to set the height of it makes the most sense to add it to the page config. You will have to do it in the yaml editor for the page, there is no UI access to it.

See “screen” here:

For the record you don’t need to define all those 100% settings as each will simply inherit or override the previous ones, in the order in which they are presented, if that makes sense.
So here you would simply define Width and Width (XL) and leave the others blank.

No harm done if you do define them though, you just define a bunch of CSS that’s not necessary.

1 Like

I tried my solution but unfortunately I can not distinguish the devices at all.
I tried your approach but maybe I do something wrong:

On the page the upper part looks like this incl. your code with some extreme values for testing.

config:
  stylesheet: |
    @media screen and (max-width: 1000px) {
      .mobile-height {
        height: 500px;
      }
    }
  label: OverviewTest2
  sidebar: true
blocks: null
masonry:
  - component: oh-masonry
...

The upper part of the widget looks like this:

uid: Cell_Notification
tags: []
props:
  parameters:
    - description: HEX or rgba
      label: Backgroundcolor
      name: bgcolor
      required: false
      type: TEXT
    - description: Page which will be opened as popup
      label: Page ID
      name: page
      required: false
timestamp: Nov 29, 2023, 2:59:59 PM
component: f7-card
config:
  style:
    background: url(/static/taube_b60.webp)
    background-size: cover
    class: 
      - padding: 0px
      - mobile-height
    height: '=items.Notification_Verlassen_ShowWidget.state =="ON" ? "130px" : items.Notification_Schlafen_ShowWidget.state =="ON" ?"130px" : "80px"'
    margin-bottom: 5px
    margin-left: "=device.desktop ? '5px' : device.webView ? '5px': '-5px'"
    margin-right: "=device.desktop ? '5px' : device.webView ? '5px': '-5px'"
    margin-top: 5px
    noShadow: false
slots:
  content:
    - component: f7-block
...

Any hint what is wrong?
Thanks

I see two things:

  1. You have the class property inside the style object (and possibly confused with the padding style), which probably means that your classes are not being assigned properly. The class property should be a direct child of the config:
component: f7-card
config:
  class: 
      - mobile-height
  style:
    background: url(/static/taube_b60.webp)
    background-size: cover
    padding: 0px
    height: '=items.Notification_Verlassen_ShowWidget.state =="ON" ? "130px" : items.Notification_Schlafen_ShowWidget.state =="ON" ?"130px" : "80px"'
  1. You are still setting the height of the card directly in the widget. That declaration will take precedence over the the scope of the declaration from the media query. Either remove the height style from the widget or, if you need that height style for other reasons, use 500px !important; in the style sheet.

Works, thanks you!

Anyhow: as I have other objects I want to manipulate depend on the screen size, is there any way I can use this as a variable within the widget, e.g. for if statements?

Best

The link I provided above shows that the screen object is the way to get the width of the screen in your widget expressions.

You are right, I have overseen commenting.
I tested but somehow it does not work as expected.

color: '=screen.width <= 1500 ? "red" : "white"'

On a 1080p screen (notebook), I would expect color change when shrinking window size - but color stays white all time. I I change to 2000, is stays red all time. Does not make sense for me!

I see two issues:

  1. You are using screen.width that is the physical size of the screen which (I assume) does not change. The second part of the docs there say:

The two properties viewAreaWidth and viewAreaHeight are added on top.

These two properties tell you how much of the screen is available to the app and this will change if you change the window size.

  1. The screen object is not calculated dynamically. It will be refreshed only any time the widget is redrawn or refreshed, but it will not track instantaneous changes to the screen/window parameters.

If you are in the widget editor and make a change to the window size, you must hit the Redraw button or press ctrl + r and then you should see viewAreaWidth expressions respond to the change.

1 Like

Thanks, got it working!
Actually I always saved the widget anyhow and tried the page but have not reloaded. I saw some unclear behaviour as the widget redraws automatically every ca 5 sec => explained now.

color: '=screen.viewAreaWidth <= 1000 ? "red" : "white"'