New Lovelace card – Flex Cells Card

Looks amazing! Thanks for sharing!

Nice! What did you do to get this?

Thanks! Are you asking about the card layout, or the data behind it?

I just added a new example:

dark-charging
light-disconnect

While creating this example, I found two bugs that I fixed and added logical operators because they were definitely missing. So, here’s a new version.

  • v0.17.0 —
    • Added “AND/OR” logical operators in dynamic rules.
    • Added new fields in dynamic cell rules for the “Overwrite with entity/metadata” option: Date/Time format & Text override, Entity display, Rescale.
    • Fixed an issue related to changing the number of columns and the disappearance of unsaved dynamic rules.
    • Fixed an issue related to the column width for the “auto” value.
1 Like

Like that, good work!
Would you share your code? Are the Min/Max Values Helpers, or created automatically? Thanks

Thanks. Here you go.

rows:
  - cells:
      - type: string
        value: Temperaturen und Luftfeuchtigkeit
        align: center
        style:
          text_transform: ""
          background: "#ff9f09"
          font_size: 20px
          bold: false
          underline: false
      - type: string
        value: ""
        align: left
        style:
          text_transform: ""
      - type: string
        value: ""
        align: right
      - type: string
        value: ""
        align: right
      - type: string
        value: ""
        align: right
      - type: string
        value: ""
        align: right
    merge_columns: true
  - type: separator
    separator:
      color: "#d0d7de"
      background: ""
      style: solid
      thickness: 1
      length: 100%
      align: stretch
      opacity: 1
      margin_top: 0
      margin_bottom: 0
    cells: []
  - cells:
      - type: string
        value: Sensor
        align: left
        style:
          text_transform: ""
      - type: icon
        value: mdi:temperature-celsius
        align: right
        style:
          text_transform: ""
      - type: string
        value: Min
        align: right
        style:
          text_transform: ""
      - type: string
        value: Max
        align: right
      - type: icon
        value: mdi:water-percent
        align: right
      - type: icon
        value: mdi:waves
        align: right
        style:
          text_transform: ""
    custom_css_enabled: true
    custom_css: |
      tr {
         background-color:#30884a;

      }
  - type: separator
    separator:
      color: "#d0d7de"
      background: ""
      style: solid
      thickness: 1
      length: 100%
      align: stretch
      opacity: 1
      margin_top: 0
      margin_bottom: 0
    cells: []
  - cells:
      - type: string
        value: Carport
        align: left
        style:
          text_transform: ""
      - type: entity
        value: sensor.esph_carport_temp
        align: right
        use_entity_unit: true
        precision: 1
        style:
          text_transform: ""
          font_size: 120%
          background: ""
        dyn_color:
          - entity: sensor.esph_carport_temp
            attr: ""
            op: <
            val: "0"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
            text: ""
      - type: entity
        value: sensor.carport_stats_temp_min
        align: right
        use_entity_unit: true
        precision: 1
        dyn_color:
          - entity: sensor.carport_stats_temp_min
            attr: ""
            op: <
            val: "0"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
            text: ""
      - type: entity
        value: sensor.carport_stats_temp_max
        align: right
        use_entity_unit: true
        precision: 1
      - type: string
        value: ""
        align: right
        precision: 1
      - type: string
        value: ""
        align: right
        precision: 1
    dyn_row_rules:
      - entity: ""
        attr: ""
        op: "="
        val: ""
        val2: ""
        bg: ""
        fg: ""
  - cells:
      - type: string
        value: Eingang
        align: left
        style:
          text_transform: ""
          background: ""
      - type: entity
        value: sensor.lumi_temperature_eingang
        align: right
        style:
          text_transform: ""
          font_size: 120%
        use_entity_unit: true
        precision: 1
        dyn_color:
          - entity: sensor.lumi_temperature_eingang
            attr: ""
            op: <
            val: "0"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
            text: ""
      - type: entity
        value: sensor.aussentemp_stats_temp_min
        align: right
        use_entity_unit: true
        precision: 1
        dyn_color:
          - entity: sensor.aussentemp_stats_temp_min
            attr: ""
            op: <
            val: "0"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
            text: ""
      - type: entity
        value: sensor.aussentemp_stats_temp_max
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.lumi_humidity_eingang
        align: right
        use_entity_unit: true
        precision: 1
        dyn_color:
          - entity: sensor.lumi_humidity_eingang
            attr: ""
            op: ">="
            val: "60"
            bg: "#ff9f09"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
          - entity: sensor.lumi_humidity_eingang
            attr: ""
            op: ">="
            val: "70"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
      - type: entity
        value: sensor.absolute_humi_outdoor
        align: right
        use_entity_unit: true
        precision: 1
    custom_css_enabled: true
    custom_css: |
      tr {
         background-color:#4a1c44;

      }
  - type: separator
    separator:
      color: "#d0d7de"
      background: ""
      style: solid
      thickness: 1
      length: 100%
      align: stretch
      opacity: 1
      margin_top: 0
      margin_bottom: 0
    cells: []
  - cells:
      - type: string
        value: Büro
        align: left
        style:
          text_transform: ""
      - type: entity
        value: sensor.sonoff_th_buro_temperature
        align: right
        use_entity_unit: true
        precision: 1
        style:
          text_transform: ""
          font_size: 120%
      - type: entity
        value: sensor.buro_stats_temp_min
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.buro_stats_temp_max
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.sonoff_th_buro_humidity
        align: right
        precision: 1
        use_entity_unit: true
        dyn_color:
          - entity: sensor.sonoff_th_buro_humidity
            attr: ""
            op: ">="
            val: "60"
            bg: "#ff9f09"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
          - entity: sensor.sonoff_th_buro_humidity
            attr: ""
            op: ">="
            val: "70"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
      - type: string
        value: ""
        align: left
        precision: 1
  - cells:
      - type: string
        value: Gäste
        align: left
        style:
          text_transform: ""
      - type: entity
        value: sensor.tuya_th_gz_temperature
        align: right
        use_entity_unit: true
        precision: 1
        style:
          text_transform: ""
          font_size: 120%
      - type: entity
        value: sensor.gz_stats_temp_min
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.gz_stats_temp_max
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.tuya_th_gz_humidity
        align: right
        use_entity_unit: true
        precision: 1
        dyn_color:
          - entity: sensor.tuya_th_gz_humidity
            attr: ""
            op: ">="
            val: "60"
            bg: "#ff9f09"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
          - entity: sensor.tuya_th_gz_humidity
            attr: ""
            op: ">="
            val: "70"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
      - type: string
        value: ""
        align: right
        precision: 1
    custom_css_enabled: true
    custom_css: |
      tr {
         background-color:#4a1c44;

      }
  - cells:
      - type: string
        value: SZ
        align: left
        style:
          text_transform: ""
      - type: entity
        value: sensor.lumi_thp_sz_temperatur
        align: right
        use_entity_unit: true
        precision: 1
        style:
          text_transform: ""
          font_size: 120%
      - type: entity
        value: sensor.sz_stats_temp_min
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.sz_stats_temp_max
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.lumi_thp_sz_humidity
        align: right
        use_entity_unit: true
        precision: 1
        dyn_color:
          - entity: sensor.lumi_thp_sz_humidity
            attr: ""
            op: ">="
            val: "60"
            bg: "#ff9f09"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
          - entity: sensor.lumi_thp_sz_humidity
            attr: ""
            op: ">="
            val: "70"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
      - type: string
        value: ""
        align: right
        precision: 1
  - type: separator
    separator:
      color: "#d0d7de"
      background: ""
      style: solid
      thickness: 1
      length: 100%
      align: stretch
      opacity: 1
      margin_top: 0
      margin_bottom: 0
    cells: []
  - cells:
      - type: string
        value: WZ
        align: left
        style:
          text_transform: ""
      - type: entity
        value: sensor.sonoff_th_wz_temperature
        align: right
        use_entity_unit: true
        precision: 1
        style:
          text_transform: ""
          font_size: 120%
      - type: entity
        value: sensor.wz_stats_temp_min
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.wz_stats_temp_max
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.sonoff_th_wz_humidity
        align: right
        use_entity_unit: true
        dyn_color:
          - entity: sensor.sonoff_th_wz_humidity
            attr: ""
            op: ">="
            val: "60"
            bg: "#ff9f09"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
          - entity: sensor.sonoff_th_wz_humidity
            attr: ""
            op: ">="
            val: "70"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
      - type: string
        value: ""
        align: right
        precision: 1
    custom_css_enabled: true
    custom_css: |
      tr {
         background-color:#4a1c44;

      }
  - type: separator
    separator:
      color: "#d0d7de"
      background: ""
      style: solid
      thickness: 1
      length: 100%
      align: stretch
      opacity: 1
      margin_top: 0
      margin_bottom: 0
    cells: []
  - cells:
      - type: string
        value: Hobby
        align: left
        style:
          text_transform: ""
      - type: entity
        value: sensor.lumi_temperature_hobbyraum
        align: right
        use_entity_unit: true
        precision: 1
        style:
          text_transform: ""
          font_size: 120%
      - type: entity
        value: sensor.hobbyraum_stats_temp_min
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.hobbyraum_stats_temp_max
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.lumi_humidity_hobbyraum
        align: right
        use_entity_unit: true
        precision: 1
        dyn_color:
          - entity: sensor.lumi_humidity_hobbyraum
            attr: ""
            op: ">="
            val: "60"
            bg: "#ff9f09"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
          - entity: sensor.lumi_humidity_hobbyraum
            attr: ""
            op: ">="
            val: "70"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
      - type: entity
        value: sensor.absolute_humi_hobbyraum
        align: right
        precision: 1
        use_entity_unit: true
  - cells:
      - type: string
        value: Keller N
        align: left
        style:
          text_transform: ""
      - type: entity
        value: sensor.lumi_temperature_keller1
        align: right
        use_entity_unit: true
        precision: 1
        style:
          text_transform: ""
          font_size: 120%
      - type: entity
        value: sensor.keller1_stats_temp_min
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.keller1_stats_temp_max
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.lumi_humidity_keller1
        align: right
        use_entity_unit: true
        dyn_color:
          - entity: sensor.lumi_humidity_keller1
            attr: ""
            op: ">="
            val: "60"
            bg: "#ff9f09"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
          - entity: sensor.lumi_humidity_keller1
            attr: ""
            op: ">="
            val: "70"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
      - type: entity
        value: sensor.absolute_humi_keller_1
        align: right
        precision: 1
        use_entity_unit: true
    custom_css_enabled: true
    custom_css: |
      tr {
         background-color:#4a1c44;

      }
  - cells:
      - type: string
        value: Keller S
        align: left
        style:
          text_transform: ""
      - type: entity
        value: sensor.lumi_thp_keller_2_temperature
        align: right
        use_entity_unit: true
        precision: 1
        style:
          text_transform: ""
          font_size: 120%
      - type: entity
        value: sensor.keller2_stats_temp_min
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.keller2_stats_temp_max
        align: right
        use_entity_unit: true
        precision: 1
      - type: entity
        value: sensor.lumi_thp_keller_2_humidity
        align: right
        precision: 1
        use_entity_unit: true
        dyn_color:
          - entity: sensor.lumi_thp_keller_2_humidity
            attr: ""
            op: ">="
            val: "60"
            bg: "#ff9f09"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
          - entity: sensor.lumi_thp_keller_2_humidity
            attr: ""
            op: ">="
            val: "70"
            bg: "#991a1a"
            fg: ""
            overwrite: entity
            overwrite_entity: ""
            overwrite_attr: ""
      - type: entity
        value: sensor.absolute_humi_keller_2
        align: right
        precision: 1
        use_entity_unit: true
column_count: 6
card_padding: ""
overflow_x: true
header_from_first_row: false
zebra: true
narrow_breakpoint: ""
text_size: 14px
cell_padding:
  top: 4
  right: 5
  bottom: 8
  left: 5
custom_template_enabled: false
custom_template_html: ""
type: custom:flex-cells-card
zebra_ignore_separators: false
column_widths:
  - auto
grid_options:
  columns: full
  rows: 1
2 Likes
  • v0.18.0 —
    • Added attribute editing using slider and switch.

Thanks to this new functionality, the media player example has been greatly simplified. You no longer need to create automations or add input_numbers to the system - just FCC and nothing else.

I’ve also created two new examples using the new functionality. The first one controls a window blind:
dark_open
light_closing

The second one controls lighting:
dark
light

I’ve released a new version, with three new examples and updated screenshots. If you like this card, please consider giving it a :star: on GitHub.

  • v0.19.0 —
    • Added proper ha-card wrapper and removed the custom border so the card behaves like a normal Lovelace card (e.g., looks correct inside vertical-stack-in-card). Kept the “card” class intact, so any existing CSS targeting it should still work.
    • Added RAW token to “Date/Time format & Text override” so you can inject the unformatted value; e.g., set the format to “[light is: ]RAW” to render “light is: on”.
    • Fixed FCC template parsing to only consider “mode/as” attributes for “text” mode and accept row/column values ​​in single quotes.






1 Like

Does anybody know where this card is being documented?

I could not find any documentation of the tags and I’m strugling with custom_template_html

The following code is not working, it’s simply doing nothing but should draw a box-shadow for the hole card.

custom_template_html: |
  <style>
    .card {
      box-shadow:
        inset -6px 6px 12px hsla(43, 95%, 80%, 0.06), 
        inset 6px -6px 12px rgba(0, 0, 0, 0.3);
    }
  </style>
  <fcc />

I also tried with card_mod, which ich also not working, but probably not needed, when custom_template_html would do the job.

Update: I found my error, it was just 1 line above.

custom_template_enabled: true

That only happens when switching between GUI and YAML, otherwise this flag is handled automaticaly.

Next question where I would need a documentation of this new card, that I’m really starting to like. How can I set the opacity of an icon according to the brightness of a light?

With jinja templating I would solve it like this:

      - type: icon
        value: mdi:lightbulb
        align: right
        style:
          color: |
            {% if is_state('light.bed_light', 'on') %}
              {% set bri = state_attr('light.bed_light', 'brightness') | float(0) %}
              {% set opacity = (bri / 255 * 0.8 + 0.2) %}
              hsla(195, 99%, 50%, {{ opacity }})
            {% else %}
              grey
            {% endif %}

But this code is just giving a white icon.

What I could solve is a dynamic color based on the state, but not based on the brightness.

        style:
          color: grey
        dyn_color:
          - conditions:
              - entity: light.bed_light
                op: "="
                val: "on"
            fg: var(--primary-color)

The only documentation is the main project page, where you’ll find both the templates section and examples with and without templates.

However, I’ve tried to make the graphical editor user-friendly enough to avoid extensive documentation.

If you display an entity icon, it will respond to the lighting brightness by default. Even if you change this icon to a different one using a rule, and even if you change its color, the brightness should still be dynamic by default. See the lighting examples.

Thanks a lot for your fast support, it’s working now.
I just had to change the type from icon to entity.

I also found the code now for the examples, that’s really helpfull.
There are so many posibilities with this card, it will take a while to explore them all.

1 Like

Is there any way how to change the padding-bottom for the hole card?

I only found ways to change the line padding
and the padding for the hole card equaly in all directions.

custom_template_enabled: true
custom_template_html: |-
  <style>
    .fcc-template-card {
      padding-bottom: 100px !important;
    }
  </style>
  <fcc/>
1 Like

Thanks a lot, it’s really nice what’s possible with this great card.

I have used 2 cards, one for the first line, and the 2nd one for the rooms.
Both are stacked together with the vertical-stack card.
To make the border shown as one, it’s modified via style.

Here the style code for the 2nd card, the first one is just mirrored.

      custom_template_enabled: true
      custom_template_html: |
        <style>
          .fcc-template-card {
            margin-top: -20px;
            border-top: none !important;
            border-top-left-radius: 0px !important;
            border-top-right-radius: 0px !important;
            padding-bottom: 6px !important;
          }
        </style>
        <fcc />

1 Like

That’s always great to hear! There will be even more features coming - for example, yesterday I posted a pre-release that lets you adjust hue and saturation using a slider.

If you use custom:vertical-stack-in-card you won’t have to mess with the border, this card gives you one border by default.

1 Like

I have tried with both options and they are working,
but in both cases I’m not able to add a box-shadow via card_mod any more.

card_mod:
  style: |
    ha-card { 
      box-shadow:
        inset -6px  6px 12px hsla(43, 95%, 80%, 0.06),
        inset  6px -6px 12px rgba(0, 0, 0, 0.3);
    }

Does the DOM change here so that I need to adopt my card_mod code?

I already tried some other options like :host or vertical-stack-in-card instead of ha-card, but nothing worked in this stacked case, while without stacking it works fine.

If you add shading to a VSIC and then apply an FCC over it, the FCC will cover the shading. Set the FCC background to transparent so you can see what’s underneath.

type: custom:vertical-stack-in-card
cards:
  - rows:
      - cells:
          - type: string
            value: FCC1
            align: left
            style:
              text_transform: ""
    column_count: 1
    card_padding: ""
    overflow_x: true
    header_from_first_row: false
    zebra: false
    narrow_breakpoint: ""
    text_size: ""
    cell_padding:
      top: 4
      right: 0
      bottom: 4
      left: 0
    custom_template_enabled: false
    custom_template_html: ""
    type: custom:flex-cells-card
  - rows:
      - cells:
          - type: string
            value: FCC2
            align: left
            style:
              text_transform: ""
    column_count: 1
    card_padding: ""
    overflow_x: true
    header_from_first_row: false
    zebra: false
    narrow_breakpoint: ""
    text_size: ""
    cell_padding:
      top: 4
      right: 0
      bottom: 4
      left: 0
    custom_template_enabled: true
    custom_template_html: |-
      <style>
      .fcc-template-card {
        background-color: transparent !important;
      }
      </style>
      <fcc />
    type: custom:flex-cells-card
card_mod:
  style: |
    ha-card { 
      box-shadow:
        inset -6px  6px 12px hsla(43, 95%, 80%, 0.06),
        inset  6px -6px 12px rgba(0, 0, 0, 0.3);
      background-color: red;
    }

You can also apply shading top+left+right for the first FCC and bottom/left/right for the second FCC, then card_mod won’t be necessary. ChatGPT handles these types of problems quite well.

Pressing F12 in your browser will give you access to the “inspect tool” – this makes it very easy to see elements/classes/CSS settings.

Thanks a lot, it’s perfectly working.

I only understand partly why, but I got 2 books about CSS and started reading the first one.
After finishing the 2nd one I hopefully understand these things not only partly.

I’ve added the Crowdin service to the project. This allows us to translate into any language on crowdin.com, and I can “pull” those translations into the FCC. The source language is English. If a string isn’t translated, it falls back to English - so there’s no need to translate everything. In the meantime, I’ve discovered that clicking the “Request New Language” button doesn’t work, so let me know in another way which languages ​​you’d like to translate, for example here.

The README includes a quick start guide for translators:
https://github.com/michalowskil/flex-cells-card#translations

In addition to the above, I’m releasing the new version v0.20.0. This new functionality already has a dedicated example.

  • v0.20.0 —
    • Added sliders for hue and saturation.
    • Integrating FCC with crowdin.com.