Facebook Album Images on OpenHAB's main UI

Note: My CSS skills are close to nil. I’d appreciate any pointers to improve my layout / widget.

I upload kids and family photos into Facebook albums, and I really enjoyed showing them on Google Nest Hub display, but recently they disabled this feature.

I managed to pull my albums and photos from Facebok using GraphAPI with the help of Koala + JRuby

The photos then get displayed on OH3’s MainUI as a widget. I’m still struggling with creating a proper looking widget / layout on mainui, and my design and css skills are seriously lacking at the moment.

Problems:

  • I set a css transition ease-in-out but it isn’t working when a new url is given to the background property (by updating an openhab item). It seems to work only if the new image is already in the browser’s cache.
  • I don’t know how to make the oh-label-card's background transparent
  • Unexciting layout overall - needs improvement
  • I’d like to make the chevrons (left and right) bigger, vertically centered on the left and right of the image, but haven’t tried css positioning yet.
  • It’d be great to make it also swipable left/right
  • I have a feeling that I need to let the UI keep a list of several photos for the swipe left/right to work more smoothly
  • I’d like to put the weather icon and current temp on top of the image and when clicked, will pop up the weather widget.

So here’s my current mainui screen - far from the end result I wanted:

The photo itself it displayed as a background image of an f7-card, just so I can have the navigation arrows and caption sit on top of it. I’m sure there’s a better way. The background url is linked to an openhab item which gets updated periodically (e.g. every minute).

The image caption sits inside an oh-label-card but it has this dark background that I don’t know how to make the background transparent. The best I could do was to lower the opacity of the whole oh-label-card, but that also makes the caption faded.

I’d like to split the date, image title, and album name into three separate elements, making the title bigger, and the date smaller, etc and position them differently.

Here’s my widget yaml FWIW

uid: widget_photoframe
tags: []
props:
  parameters:
    - context: item
      description: The image to display
      label: Image Item
      name: image
      required: false
      type: TEXT
    - context: item
      description: The image title
      label: Image Title
      name: title
      required: false
      type: TEXT
    - context: item
      description: The image description
      label: Description
      name: description
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Mar 16, 2021, 1:50:26 AM
component: f7-card
config:
  style:
    height: 100%
    width: 100%
    background: transparent
slots:
  default:
    - component: f7-card
      config:
        style:
          height: 100%
          width: 100%
          -webkit-transition: background-image 0.5s ease-in-out
          transition: background-image 0.5s ease-in-out
          background: ='no-repeat center 100% / contain url(' + items[props.image].state + ')'
          opacity: 1
      slots:
        default:
          - component: f7-row
            config:
              style:
                position: absolute
                bottom: 0
                left: 0
                width: 100%
            slots:
              default:
                - component: f7-col
                  config:
                    style:
                      width: 10%
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: command
                          actionItem: PhotoFrame_Prev
                          actionCommand: ON
                          iconF7: chevron_left
                - component: f7-col
                  config:
                    style:
                      width: 80%
                      overflow: hidden
#                      opacity: 30%
                  slots:
                    default:
                      - component: oh-label-card
                        config:
                          item: =props.title
                          background: transparent # This doesn't seem to work
                          fontSize: 0.8rem
                - component: f7-col
                  config:
                    style:
                      width: 10%
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: command
                          actionItem: PhotoFrame_Next
                          actionCommand: ON
                          iconF7: chevron_right

Hey @JimT

It should work with your code, if the item gets updated with a new image url (if the url doens’t change the item won’t get updated) - in a quick test everything seems to works fine.


Simplest soloution would be to get rid of the ’ oh-label-card’ and using another component here. Something like this would work:

Transparent card (YAML)
- component: f7-card
  config:
    class:
      - display-flex
      - justify-content-center
      - align-items-center
    style:
      height: 60px
      background: rgba(255,255,255,.5)
      font-size: .8rem
  slots:
    default:
      - component: Label
        config:
          text: =items[props.title].state

If you want to use the button-component here, you could adjust the button-height and the iconSize prop:

Adjusting the icon size in buttons (YAML)
- component: oh-button
  config:
    action: command
    actionItem: PhotoFrame_Prev
    actionCommand: ON
    iconF7: chevron_left
    iconSize: 50
    style:
      --f7-button-height: 60px

Generally doable


Exactly - for example a concetenated string with the the url and the description text for each photo as an item state would work here and could be used in a swiper. You have to use the ‘oh-repeater’ component to make it dynamic. In the below example, the state of your item would be:

https://yourimageurl1.com/something.png,A nice image;https://yourimageurl2.com/something.png,Another one

It might be usefull to adjust the used delimeter here, as ‘,’ and ‘;’ might occur in your description text - but I’m sure you can do that easily as it seems you have some developing experience.

All images gets refreshed, if the item state string changes - so reordering your images or adding new ones would work.

Dynamic image swiper (YAML)
- component: f7-swiper
  config:
    navigation: true
    params:
      initalSlide: 0
      runCallbacksOnInit: true
      grabCursor: true
      observer: true
      observeSlideChildren: true
      updateOnWindowResize: true
      spaceBetween: 5
      mousewheel: true
      keyboard: true
      watchOverflow: true
      slidesPerView: 1
    style:
      --swiper-navigation-size: 50px
      --swiper-navigation-color: white
      z-index: 0
  slots:
    default:
      - component: oh-repeater
        config:
          sourceType: range
          for: images
          rangeStart: 1
          rangeStop: =items[props.image].state.split(';').length
          fragment: true
        slots:
          default:
            - component: f7-swiper-slide
              config:
                class:
                  - display-flex
                  - justify-content-center
                  - align-items-center
                style:
                  width: 100%
                  height: 100%
                  position: relative
              slots:
                default:
                  - component: oh-image
                    config:
                      url: =items[props.image].state.split(';')[loop.images_idx].split(',')[0]
                      style:
                        width: 100%
                        height: 100%
                        object-fit: contain # You could also use 'cover' here and set a fixed height, which would compensate for differences in image-size
                  - component: f7-card
                    config:
                      class:
                        - display-flex
                        - justify-content-center
                        - align-items-center
                      style:
                        position: absolute
                        bottom: 0
                        height: 60px
                        width: 80%
                        background: rgba(255,255,255,.75)
                        font-size: 1.25rem
                        z-index: 999
                    slots:
                      default:
                        - component: Label
                          config:
                            text: =items[props.image].state.split(';')[loop.images_idx].split(',')[1]

P.S. You could also adjust the chevron size and color here easily, with the f7 css-variables

--swiper-navigation-size: 50px
--swiper-navigation-color: white

Possible. You just have to add a component on top of the root component and overlaying it with a ‘oh-link’ component to trigger the popup-action. Something like this should work:

Weather overlay example (YAML)
    - component: f7-card
      config:
        class:
          - padding
        style:
          position: absolute
          top: 40px
          left: 60px
          background: rgba(255,255,255,.5)
          z-index: 2
          --weather-card-color: 255,255,255
          --weather-card-text-shadow-color: 0,0,0
          --weather-card-text-color: rgba(var(--weather-card-color),1)
          color: var(--weather-card-text-color)
          --weather-font-size-xxsmall: 12px
          --weather-font-size-large: 26px
          --weather-font-size-xlarge: 60px
          --weather-font-size-xxlarge: 70px
          --weather-text-shadow-light: 2px 2px rgba(var(--weather-card-text-shadow-color),.15)
          --weather-text-shadow-strong: 2px 2px rgba(var(--weather-card-text-shadow-color),.35)
          --weather-text-transform-time: uppercase
      slots:
        default: 
          - component: oh-link
            config:
              action: popup
              actionModal: widget:weatherCard
              actionModalConfig: 
                itemPrefix: OneCallAPIweatherandforecast_
                forecastHours: "12"
                forecastDays: "3"
                sunIndicator: true
                locationTitle: Some city
              style:
                position: absolute
                width: 100%
                height: 100%
                top: 0
                left: 0
                z-index: 99
          - component: Label
            config:
              text: Some city
              style:
                white-space: nowrap
                overflow: hidden
                text-overflow: ellipsis
                letter-spacing: .75px
                font-size: var(--weather-font-size-large)
                text-shadow: var(--weather-text-shadow-strong)
                font-weight: 600
          - component: Label
            config:
              text: =dayjs().format('DD. MMMM YYYY')
              style:
                white-space: nowrap
                overflow: hidden
                text-overflow: ellipsis
                color: rgba(var(--weather-card-color),.7)
                letter-spacing: .75px
                font-size: var(--weather-font-size-xxsmall)
                text-shadow: var(--weather-text-shadow-light)
          - component: f7-block
            config:
              class:
                - display-flex
                - align-items-center
                - justify-content-flex-start
              style:
                flex-wrap: nowrap
            slots:
              default:
                - component: f7-icon
                  config:
                    f7: "=(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01d') ? 'sun_max_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01n') ? 'moon_stars_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02d') ? 'cloud_sun_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02n') ? 'cloud_moon_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03d') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03n') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04d') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04n') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09d') ? 'cloud_heavyrain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09n') ? 'cloud_heavyrain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10d') ? 'cloud_sun_rain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10n') ? 'cloud_moon_rain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11d') ? 'cloud_sun_bolt_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11n') ? 'cloud_moon_bolt_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13d') ? 'cloud_snow_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13n') ? 'cloud_snow_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50d') ? 'cloud_fog_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50n') ? 'cloud_fog_fill' : '?'"
                    style:
                      text-shadow: var(--weather-text-shadow-strong)
                      font-size: var(--weather-font-size-xxlarge)
                      padding-top: 5px
                      padding-bottom: 5px
                      margin-right: 16px
                - component: Label
                  config:
                    text: "=Math.round(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Temperature'].state.split(' ')[0]) + '°'"
                    style:
                      white-space: nowrap
                      overflow: hidden
                      text-overflow: ellipsis
                      text-shadow: var(--weather-text-shadow-strong)
                      font-size: var(--weather-font-size-xlarge)
                      line-height: var(--weather-font-size-xlarge)
                      font-weight: 600
                      display: inline

Everything cobbled together could look something like this (Just a quick and dirty approach during a boring meeting - so it would be good checking everything again :slight_smile: ):

image-slider

Dynamic image slider weather overlay thingy (YAML)
uid: widget_photoframe
tags: []
props:
  parameters:
    - description: <b>Optional prefix</b> for item names
      label: Item prefix
      name: itemPrefix
      required: false
      type: TEXT
    - context: item
      description: Item which holds the image-url and the title
      label: Image/Title Item
      name: image
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Mar 16, 2021, 1:50:26 AM
component: f7-block
config:
  style:
    position: relative
slots:
  default:
    - component: f7-swiper
      config:
        navigation: true
        params:
          initalSlide: 0
          runCallbacksOnInit: true
          grabCursor: true
          observer: true
          observeSlideChildren: true
          updateOnWindowResize: true
          spaceBetween: 5
          mousewheel: true
          keyboard: true
          watchOverflow: true
          slidesPerView: 1
        style:
          --swiper-navigation-size: 50px
          --swiper-navigation-color: white
          z-index: 0
      slots:
        default:
          - component: oh-repeater
            config:
              sourceType: range
              for: images
              rangeStart: 1
              rangeStop: =items[props.image].state.split(';').length
              fragment: true
            slots:
              default:
                - component: f7-swiper-slide
                  config:
                    class:
                      - display-flex
                      - justify-content-center
                      - align-items-center
                    style:
                      width: 100%
                      height: 100%
                      position: relative
                  slots:
                    default:
                      - component: oh-image
                        config:
                          url: =items[props.image].state.split(';')[loop.images_idx].split(',')[0]
                          style:
                            width: 100%
                            height: 100%
                            object-fit: contain # You could also use 'cover' here and set a fixed height, which would compensate for differences in image-size
                      - component: f7-card
                        config:
                          class:
                            - display-flex
                            - justify-content-center
                            - align-items-center
                          style:
                            position: absolute
                            bottom: 0
                            height: 60px
                            width: 80%
                            background: rgba(255,255,255,.75)
                            font-size: 1.25rem
                            z-index: 999
                        slots:
                          default:
                            - component: Label
                              config:
                                text: =items[props.image].state.split(';')[loop.images_idx].split(',')[1]
    - component: f7-card
      config:
        class:
          - padding
        style:
          position: absolute
          top: 40px
          left: 60px
          background: rgba(255,255,255,.5)
          z-index: 2
          --weather-card-color: 255,255,255
          --weather-card-text-shadow-color: 0,0,0
          --weather-card-text-color: rgba(var(--weather-card-color),1)
          color: var(--weather-card-text-color)
          --weather-font-size-xxsmall: 12px
          --weather-font-size-large: 26px
          --weather-font-size-xlarge: 60px
          --weather-font-size-xxlarge: 70px
          --weather-text-shadow-light: 2px 2px rgba(var(--weather-card-text-shadow-color),.15)
          --weather-text-shadow-strong: 2px 2px rgba(var(--weather-card-text-shadow-color),.35)
          --weather-text-transform-time: uppercase
      slots:
        default: 
          - component: oh-link
            config:
              action: popup
              actionModal: widget:weatherCard
              actionModalConfig: 
                itemPrefix: OneCallAPIweatherandforecast_
                forecastHours: "12"
                forecastDays: "3"
                sunIndicator: true
                locationTitle: Some city
              style:
                position: absolute
                width: 100%
                height: 100%
                top: 0
                left: 0
                z-index: 99
          - component: Label
            config:
              text: Some city
              style:
                white-space: nowrap
                overflow: hidden
                text-overflow: ellipsis
                letter-spacing: .75px
                font-size: var(--weather-font-size-large)
                text-shadow: var(--weather-text-shadow-strong)
                font-weight: 600
          - component: Label
            config:
              text: =dayjs().format('DD. MMMM YYYY')
              style:
                white-space: nowrap
                overflow: hidden
                text-overflow: ellipsis
                color: rgba(var(--weather-card-color),.7)
                letter-spacing: .75px
                font-size: var(--weather-font-size-xxsmall)
                text-shadow: var(--weather-text-shadow-light)
          - component: f7-block
            config:
              class:
                - display-flex
                - align-items-center
                - justify-content-flex-start
              style:
                flex-wrap: nowrap
            slots:
              default:
                - component: f7-icon
                  config:
                    f7: "=(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01d') ? 'sun_max_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01n') ? 'moon_stars_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02d') ? 'cloud_sun_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02n') ? 'cloud_moon_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03d') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03n') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04d') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04n') ? 'cloud_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09d') ? 'cloud_heavyrain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09n') ? 'cloud_heavyrain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10d') ? 'cloud_sun_rain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10n') ? 'cloud_moon_rain_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11d') ? 'cloud_sun_bolt_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11n') ? 'cloud_moon_bolt_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13d') ? 'cloud_snow_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13n') ? 'cloud_snow_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50d') ? 'cloud_fog_fill' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50n') ? 'cloud_fog_fill' : '?'"
                    style:
                      text-shadow: var(--weather-text-shadow-strong)
                      font-size: var(--weather-font-size-xxlarge)
                      padding-top: 5px
                      padding-bottom: 5px
                      margin-right: 16px
                - component: Label
                  config:
                    text: "=Math.round(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Temperature'].state.split(' ')[0]) + '°'"
                    style:
                      white-space: nowrap
                      overflow: hidden
                      text-overflow: ellipsis
                      text-shadow: var(--weather-text-shadow-strong)
                      font-size: var(--weather-font-size-xlarge)
                      line-height: var(--weather-font-size-xlarge)
                      font-weight: 600
                      display: inline
1 Like

Hi @RGroll thanks for your awesome help!

Sorry for the noob questions to follow. Why do you need to put the Label component inside a f7-card component? Why not just use the component label directly:

- component: Label
  config:
    text: =items[props.title].state
    class:
      - display-flex
      - justify-content-center
      - align-items-center
    style:
      height: 60px
      background: rgba(255,255,255,.5)
      font-size: .8rem

More questions: Where can I find the documentation for (and pardon me if some of these are obvious):

  • all the possible values for the config: section (It would depend on the component, I guess?)
  • The list of various f7-xxx components, what they do
  • How different components interact with each other
  • Which components should/could be nested in which components
  • What could go in the style section (yes this is generally css, but what properties would affect specific components?)

I’d like to write a single document outlining all this stuff, mainly for my own reference / learning process, but I’ll probably put it up on github too. However if someone else has created such a reference, that would be splendid to know. At the moment, I feel like information is scattered in many places.

@RGroll Thanks for your pointers, It’s starting to take shape.

The data source is an openhab string item that contains the images in JSON array. Do you know of a way to run the JSON.parse only once in the UI, and use the returned object for the various objects (url, title, etc) ? As it is now, I am calling JSON.parse repeatedly every time I need the data.

Here’s my widget so far:

uid: widget_photoframe
tags: []
props:
  parameters:
    - context: item
      description: The item that contains json data for the photos
      label: Photo Data
      name: photos
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Mar 17, 2021, 1:01:57 PM
component: f7-card
config:
  style:
    width: 100%
    height: 100%
    #overflow: hidden
    background-color: transparent
    --text-shadow-color: 0,0,0
    --title-font-size: 26px
    --subtitle-font-size: 18px
    --title-text-shadow: 2px 2px rgba(var(--text-shadow-color),.35)
    --subtitle-text-shadow: 2px 2px rgba(var(--text-shadow-color),.15)
slots:
  default:
    - component: f7-swiper
      config:
        navigation: true
        params:
          initalSlide: 1
          runCallbacksOnInit: true
          grabCursor: true
          observer: true
          observeSlideChildren: true
          updateOnWindowResize: true
          spaceBetween: 0
          mousewheel: true
          keyboard: true
          watchOverflow: true
          slidesPerView: 1
          effect: cube
          speed: 800
        style:
          width: 100%
          height: 100%
          --swiper-navigation-size: 50px
          --swiper-navigation-color: white
          z-index: 0
      slots:
        default:
          - component: oh-repeater
            config:
              for: images
              sourceType: array
              in: =JSON.parse(items[props.photos].state)
              fragment: true
            slots:
              default:
                - component: f7-swiper-slide
                  config:
                    class:
                      - display-flex
                      - justify-content-center
                      - align-items-center
                    style:
                      width: 100%
                      height: 100%
                      position: relative
                  slots:
                    default:
                      - component: oh-image
                        config:
                          url: =JSON.parse(items[props.photos].state)[loop.images_idx]['url']
                          style:
                            width: 100%
                            height: 100%
                            object-fit: contain # You could also use 'cover' here and set a fixed height, which would compensate for differences in image-size
                      - component: f7-card
                        config:
                          class:
                            #- display-flex
                            - justify-content-center
                            - align-items-center
                          style:
                            position: absolute
                            bottom: 0
                            height: 80px
                            width: 100%
                            background: transparent
                            z-index: 999
                            overflow: hidden
                            text-overflow: ellipsis
                            text-align: center
                        slots:
                          default:
                            - component: Label
                              config:
                                text: =JSON.parse(items[props.photos].state)[loop.images_idx]['name']
                                style: 
                                  #width: 100%
                                  font-size: var(--title-font-size)
                                  text-shadow: var(--title-text-shadow)
                                  font-weight: 600
                                  
                            - component: Label
                              config:
                                text: =dayjs(JSON.parse(items[props.photos].state)[loop.images_idx]['created_time']).format('MMMM D, YYYY') + ' - ' + JSON.parse(items[props.photos].state)[loop.images_idx]['album']
                                style: 
                                  #width: 100%
                                  font-size: var(--subtitle-font-size)
                                  text-shadow: var(--subtitle-text-shadow)
                                  font-weight: 600
                    

Hey @JimT

Theres no problem doing it with the label only - I just thought that was what you want. I think, that your recently posted soloution with the text including the text-shadow looks kinda nice.


Yes, every component have its own config properties. I wrote down some usefull sources some time ago, which might help you here. Especially the f7 vue-documentation is very helpful.

The most important feature to see all (most?!) of the available config parameters, is the tooltip that comes up in the editor while writing - you can trigger these tooltips by pressing CTRL+Spacebar


For all f7 components, see the above mentioned f7 vue-documentation. For everything regarding the custom oh-components have a look in the docs


Most of the mentioned f7-components in the docs have examples attached to them which gives you a rough understanding of how the structure of the components should look. IN case of the f7-swiper you can find the documentation here


I’m not sure if I understand you here - the config section is for the properties and the style section is what you say, purely css.


I’m no expert here, but I think theres no way around, running the parse multiple times in the widget.

@RGroll how can I make the widget to take up the entire content of the browser window, zero margins / padding all around. Also including hiding the top navbar, date, and “Overview”? Basically I’d like the image (plus the captions) to be the only thing displayed.

There’s a photobrowser action that might be ideal for this, however, it cannot be used stand alone as the first thing that shows up when the page is loaded.

Not possible out of the box afaik - there might be ways tricking around with the use of the backdrop layer that came up when opening a modal for example.


Thats correct

@RGroll is it possible to send a command to an openhab item when at the end of the swiper slide and the user tries to go further (e.g. to the right)? The current behaviour is the right navigation arrow is disabled.

Sadly not - there is no way currently to work with slider events like activeSlide or similar. But if it’s just about removing the navigation arrow if you reach the end of the swiper you could add watchOverflow: true to the params.

I’d like to insert new image to the end of the slides and remove the first slide. Basically making it like infinite scroll to the right and left.

If it’s just about having infinite scroll, you could use loop: true
See the swiperjs documentation for more infos.

There’s a new grid layout that makes this possible!

It’s already on my snapshot build #2270. There’s still a tiny bit of margin / padding that I can’t get rid of though.

If this fit your needs, great!

CSS can be a maze, but you’re on the right track. For the transition snag, consider preloading images for smoother changes. Making oh-label-card background transparent often needs “background: none;” in CSS. For the chevrons, try vertical-align and position. Swipability might need some JavaScript magic. Regarding the weather icon, consider absolute positioning. As for real YouTube subscribers, have you thought about strategies to boost engagement? It’s a neat way to enhance your content visibility!

1 Like