Custom Header template showcase and discussion

The first element and last element should be the same, that’s what gives it the illusion of looping. This is kind of an accidental feature of Custom Header and I don’t really want to start doing “how to code in HTML and CSS”, but…

Replace Ha Rpi4: with this <div style='float: left'>Ha Rpi4:&nbsp;&nbsp;</div>

If you start adding more than 3 elements you’ll need to edit the keyframes. A tip for this would be using multiples of 48px for the margins in the keyframes.

thanks!, that helped.

sure, appreciated. It would be a great idea though to create a separate header in the community on best practices and examples for Html and CSS, especially since so many custom cards start relying on it.

Don’t know if we can do this as ‘ordinary’ members, but otherwise I would certainly invite you to do so as one of the main dev’s !

I would say that I am much closer to an ordinary member of this community than a dev. I only really started coding about a year and a half ago when I picked up HA for the first time. Though I’ve learned a bit during that time, thanks mainly to the other developers in the community, I’m probably the last person anyone should go to for best practices. :slight_smile:

Hi I have copied your code and it comes up with this.

This is my code.

exceptions:
    - conditions:
        user: cameron
      config:
        header_text: >-
              <style>
              #flipper {color:#999;}
              #flip {height:24px;overflow:hidden;}
              #flip > div > div {color:#fff;height:24px;margin-bottom:24px;display:inline-block;}
              #flip div:first-child {animation: show 10s linear infinite;}
              @keyframes show {
              0% {margin-top:-144px;}
              5% {margin-top:-96px;}
              33% {margin-top:-96px;}
              38% {margin-top:-48px;}
              66% {margin-top:-48px;}
              76% {margin-top:0px;}
              100% {margin-top:0px;}}
              #flipper p {position:fixed;color:#999; }
              </style>
              <div id=flipper><div id=flip><div><div>
              {{states('sensor.cal_home_event_event')}}</div></div><div><div>
              {{states('sensor.dark_sky_daily_summary')}}</div></div><div><div>
              {{states('sensor.dark_sky_hourly_summary')}}</div></div><div><div>
              {{states('sensor.cal_home_event_event')}}</div></div><div><div>
        button_text:
            # menu: 'M'
            # The next example is using templates. See templates page for more info.
            options: >-
                      {{ hours12 }}:{{ minutesLZ }} {{ AMPM }} - <ha-icon icon='{{states('sensor.weather_icon')}}' style='padding-bottom: 3px';></ha-icon>
                      {{states.sensor.garden_temp.state }}°

        chevrons: true
        split_mode: true
        shadow: true
        footer_mode: false
        hide_help: true
        hide_config: true
        hide_unused: true
        background_color: '#292929'
        all_tabs_color: white
        show_tabs: '0 to 20,22'
        hide_tabs: '19,21'

The button text options works fine without the Header Text.

Mind sharing your whole config so I can see what’s outside the exception?

Mainly looking for config options that are using double quotes, see the last important note

a ok, cool.

I made an exception config for the iPhone in the meantime, using @ludeeus horizontal marquee, which works fine in itself.
It does show the odd ‘n’ after each line and header though, don’t know how ro get rid of them. Since I already use the >- multiline indicator, I would have hoped this to be sufficient blocking the new lines? Maybe that is something in the footer itself, because I almost literally copied @ludeeus entry, and his screen movie clearly shows its working alright in the header.

This is my exception:

  - conditions:
      user_agent: iPhone
    config:
      footer_mode: true
      header_text: >-
        Ha Rpi4:
        {% set alerts = namespace(active=[], color="var(--google-red-500)") %}
        {% set temperature = namespace(inside=states('sensor.temperatuur_living'), outside=states('sensor.temp_current'), color="var(--primary-text-color)", symbol="°C") %}

        {% if states('sensor.weatheralerts') | float != 0 %}
        {% for alert in state_attr('sensor.weatheralerts', 'alerts') %}
        {% set alerts.active = alerts.active + [alert['title']] %}
        {% endfor %}
        {% else %}
        {% set alerts.active = alerts.active + ['No active alerts'] %}
        {% endif %}

        <marquee>
        <span style='color: {{ temperature.color }}'>
            Inside temperature: {{ temperature.inside }}{{ temperature.symbol }}
            Outside temperature: {{ temperature.outside }}{{ temperature.symbol }}
        </span>
        <span style='color: {{ alerts.color }}; margin-left: 10px;'>
            Alerts: {{ alerts.active | join('  -  ')}}
        </span>

        <span style='color: {{ temperature.color }}'>
        {{states('sensor.dark_sky_summary')}}
          Daily -  {{states('sensor.dark_sky_daily_summary')}}
          Hourly - {{states('sensor.dark_sky_hourly_summary')}}
        </span>
        </marquee>

      menu_hide: true
#      voice_hide: false
      options_hide: true

          header_text: >-
            Ha Rpi4:  
            {% set alerts = namespace(active=[], color="var(--google-red-500)") %}
            {% set temperature = namespace(inside=states('sensor.temperatuur_living'), outside=states('sensor.temp_current'), color="var(--primary-text-color)", symbol="°C") %}
            {% if states('sensor.weatheralerts') | float != 0 %}
            {% for alert in state_attr('sensor.weatheralerts', 'alerts') %}
            {% set alerts.active = alerts.active + [alert['title']] %}
            {% endfor %}
            {% else %}
            {% set alerts.active = alerts.active + ['No active alerts'] %}
            {% endif %}
            <marquee>
            <span style='color: {{ temperature.color }}'>
            Inside temperature: {{ temperature.inside }}{{ temperature.symbol }}
            Outside temperature: {{ temperature.outside }}{{ temperature.symbol }}
            </span>
            <span style='color: {{ alerts.color }}; margin-left: 10px;'>
            Alerts: {{ alerts.active | join('  -  ')}}
            </span>
            <span style='color: {{ temperature.color }}'>
            {{states('sensor.dark_sky_summary')}}
            Daily -  {{states('sensor.dark_sky_daily_summary')}}
            Hourly - {{states('sensor.dark_sky_hourly_summary')}}
            </span>
            </marquee>

yes, that works indeed… other than the blank lines in my template, what else did you change? Must have been another edit, because deleting all blank lines only solves the 2 n’s after Ha Rpi4. They’re still there at the end of the other lines? Copying your edit works 100%.

Though I know you are reluctant to create a How to CSS and HTML here, would you allow me one please? Id love to have the marquee scroll on 1 line, and start after the fixed Ha Rpi4: , just as in the vertical marquee

could that be possible here also?

        {% set alerts = namespace(active=[], color='var(--google-red-500)') %}
        {% set inside=states('sensor.temperatuur_living')%}
        {% set outside=states('sensor.temp_current')%} 
        {% set temp_color='var(--primary-text-color)'%} 
        {% set symbol='°C' %}
        {% if states('sensor.weatheralerts') | float != 0 %}
          {% for alert in state_attr('sensor.weatheralerts', 'alerts') %}
          {% set alerts.active = alerts.active + [alert['title']] %}
          {% endfor %}
        {% else %} {% set alerts.active = alerts.active + ['No active alerts'] %}
        {% endif %}
        Ha Rpi4:
        <marquee>
        <span style='color: {{ temp_color }}'>
        Inside temperature: {{ inside }}{{ symbol }},
        Outside temperature: {{ outside }}{{ symbol }},
        </span>
        <span style='color: {{ alerts.color }}; margin-left: 10px;'>
        Alerts: {{ alerts.active | join('  -  ')}},
        </span>
        <span style='color: {{ temp_color }}'>
        Summary - {{states('sensor.dark_sky_summary')}},
        Daily -  {{states('sensor.dark_sky_daily_summary')}},
        Hourly - {{states('sensor.dark_sky_hourly_summary')}}.
        </span>
        </marquee>

The n’s are because you added indents to my posted code:

Use this:

          header_text: >-
            {% set alerts = namespace(active=[], color="var(--google-red-500)") %}
            {% set temperature = namespace(inside=states('sensor.temperatuur_living'), outside=states('sensor.temp_current'), color="var(--primary-text-color)", symbol="°C") %}
            {% if states('sensor.weatheralerts') | float != 0 %}
            {% for alert in state_attr('sensor.weatheralerts', 'alerts') %}
            {% set alerts.active = alerts.active + [alert['title']] %}
            {% endfor %}
            {% else %}
            {% set alerts.active = alerts.active + ['No active alerts'] %}
            {% endif %}
            <div style='display: flex;display: -webkit-flex;'>
            <div>Ha&nbspRpi4:&nbsp;&nbsp;</div>
            <marquee>
            <span style='color: {{ temperature.color }}'>
            Inside temperature: {{ temperature.inside }}{{ temperature.symbol }}
            Outside temperature: {{ temperature.outside }}{{ temperature.symbol }}
            </span>
            <span style='color: {{ alerts.color }}; margin-left: 10px;'>
            Alerts: {{ alerts.active | join('  -  ')}}
            </span>
            <span style='color: {{ temperature.color }}'>
            {{states('sensor.dark_sky_summary')}}
            Daily -  {{states('sensor.dark_sky_daily_summary')}}
            Hourly - {{states('sensor.dark_sky_hourly_summary')}}
            </span>
            </marquee>
            </div>

Yes sure here you go. Thanks

custom_header:
  compact_mode: true
  locale: en-gb
  background: 'rgba(46, 45, 45, 1)' #transparent
  button_icons:
    menu: mdi:tools
  menu_color: '#b58e31'
  options_color: '#b58e31'
  tabs_color:
          0: >-
              {{state_attr("sensor.sitting_light_count","colour")}}
          2: '{% if states.switch.tv_plug.state == "on" %}yellow{% else %}white{% endif %}'
          3: >-
              {{'white' if is_state('sensor.open_doors_windows','0') else 'red'}}

          5: '{% if states.switch.garden_light.state == "on" %}red{% else %}white{% endif %}'
          6: >-
              {{state_attr("sensor.people_home","colour")}}
          9: '{% if states.switch.garage_lights.state == "on" %}yellow{% else %}white{% endif %}'
          12: '{% if states.light.sally_bedside.state == "on" %}green{% else %}white{% endif %}'

  tab_icons:
          6: >-
              {{state_attr("sensor.people_home","icon")}}
          14: >-
              {{states('sensor.weather_icon')}}
  exceptions:
    - conditions:
        user: cameron
      config:
        header_text: >-
              <style>
              #flipper {color:#999;}
              #flip {height:24px;overflow:hidden;}
              #flip > div > div {color:#fff;height:24px;margin-bottom:24px;display:inline-block;}
              #flip div:first-child {animation: show 10s linear infinite;}
              @keyframes show {
              0% {margin-top:-144px;}
              5% {margin-top:-96px;}
              33% {margin-top:-96px;}
              38% {margin-top:-48px;}
              66% {margin-top:-48px;}
              76% {margin-top:0px;}
              100% {margin-top:0px;}}
              #flipper p {position:fixed;color:#999; }
              </style>
              <div id=flipper><div id=flip><div><div>
              {{states('sensor.cal_home_event_event')}}</div></div><div><div>
              {{states('sensor.dark_sky_daily_summary')}}</div></div><div><div>
              {{states('sensor.dark_sky_hourly_summary')}}</div></div><div><div>
              {{states('sensor.cal_home_event_event')}}</div></div><div><div>
        button_text:
            # menu: 'M'
            # The next example is using templates. See templates page for more info.
            options: >-
                      {{ hours12 }}:{{ minutesLZ }} {{ AMPM }} - <ha-icon icon='{{states('sensor.weather_icon')}}' style='padding-bottom: 3px';></ha-icon>
                      {{states.sensor.garden_temp.state }}°

        chevrons: true
        split_mode: true
        shadow: true
        footer_mode: true
        hide_help: true
        hide_config: true
        hide_unused: true
        background_color: '#292929'
        all_tabs_color: white
        show_tabs: '0 to 20,22'
        hide_tabs: '19,21'

This is working for me, replaced some double quotes where they weren’t needed, changed indenting a bit, removed comments (I’m using storage mode so they automatically get stripped). Couldn’t tell you which fixed it, sorry, just kind of went through the whole thing at once.

custom_header:
  compact_mode: true
  locale: en-gb
  background: 'rgba(46, 45, 45, 1)'
  button_icons:
    menu: 'mdi:tools'
  menu_color: '#b58e31'
  options_color: '#b58e31'
  tabs_color:
    0: "{{state_attr('sensor.sitting_light_count','colour')}}"
    2: "{% if states.switch.tv_plug.state == 'on' %}yellow{% else %}white{% endif %}"
    3: "{{'white' if is_state('sensor.open_doors_windows','0') else 'red'}}"
    5: "{% if states.switch.garden_light.state == 'on' %}red{% else %}white{% endif %}"
    6: "{{state_attr('sensor.people_home','colour')}}"
    9: "{% if states.switch.garage_lights.state == 'on' %}yellow{% else %}white{% endif %}"
    12: "{% if states.light.sally_bedside.state == 'on' %}green{% else %}white{% endif %}"
  tab_icons:
    6: "{{state_attr('sensor.people_home','icon')}}"
    14: "{{states('sensor.weather_icon')}}"
  exceptions:
    - conditions:
        user: cameron
      config:
        header_text: >-
          <style>
          #flipper {color:#999;}
          #flip {height:24px;overflow:hidden;}
          #flip > div > div {color:#fff;height:24px;margin-bottom:24px;display:inline-block;}
          #flip div:first-child {animation: show 10s linear infinite;}
          @keyframes show {
          0% {margin-top:-144px;}
          5% {margin-top:-96px;}
          33% {margin-top:-96px;}
          38% {margin-top:-48px;}
          66% {margin-top:-48px;}
          76% {margin-top:0px;}
          100% {margin-top:0px;}}
          #flipper p {position:fixed;color:#999;}
          </style>
          <div id=flipper><div id=flip><div><div>
          {{states('sensor.cal_home_event_event')}}</div></div><div><div>
          {{states('sensor.dark_sky_daily_summary')}}</div></div><div><div>
          {{states('sensor.dark_sky_hourly_summary')}}</div></div><div><div>
          {{states('sensor.cal_home_event_event')}}</div></div><div><div>
        button_text:
            options: >-
              {{ hours12 }}:{{ minutesLZ }} {{ AMPM }} - <ha-icon icon='{{states("sensor.weather_icon")}}' style='padding-bottom: 3px';></ha-icon>
              {{ states.sensor.garden_temp.state }}°
        chevrons: true
        split_mode: true
        shadow: true
        footer_mode: true
        hide_help: true
        hide_config: true
        hide_unused: true
        background_color: '#292929'
        all_tabs_color: white
        show_tabs: '0 to 20,22'
        hide_tabs: '19,21'

ok thanks Ryan, this works perfectly now (have to study your remarks on indents, because in my current code, this doesnt cause any n’s).
The div works perfectly, and exactly as I want it, very very nice indeed!

Shortened(simplified) the namespace setup of the original entry, because I don’t need that (now) and filtered the output of the dark sky sensors a bit, because some of them use a period in the state, which I don’t want…

      header_text: >-
        {% set alerts = namespace(active=[], color='var(--google-red-500)') %}
        {% set inside=states('sensor.temperatuur_living')%}
        {% set outside=states('sensor.temp_current')%} 
        {% set temp_color='var(--primary-text-color)'%} 
        {% set symbol='°C' %}
        {% if states('sensor.weatheralerts') | float != 0 %}
          {% for alert in state_attr('sensor.weatheralerts', 'alerts') %}
          {% set alerts.active = alerts.active + [alert['title']] %}
          {% endfor %}
        {% else %} {% set alerts.active = alerts.active + ['No active alerts'] %}
        {% endif %}
        <div style='display: flex;display: -webkit-flex;'>
        <div>Ha&nbspRpi4:&nbsp;&nbsp;</div>
        <marquee>
        <span style='color: {{ temp_color }}'>
        Inside temperature: {{ inside }}{{ symbol }},
        Outside temperature: {{ outside }}{{ symbol }},
        </span>
        <span style='color: {{ alerts.color }};'>
        Alerts: {{ alerts.active | join(' - ')}},
        </span>
        <span style='color: {{ temp_color }}'>
        Summary - {{states('sensor.dark_sky_summary')}},
        Daily -  {{states('sensor.dark_sky_daily_summary').split('.')[0]}},
        Hourly - {{states('sensor.dark_sky_hourly_summary').split('.')[0]}}.
        </span>
        </marquee>

gives me all I need now. For full disclosure (…) and reference, this is my full CH config now:

#https://maykar.github.io/custom-header/#configuration/main
# https://community.home-assistant.io/t/custom-header/155399/255

header_text: >-
  <style>
  #flipper{color:#999;}
  #flip {height:24px;overflow:hidden;}
  #flip > div > div {color:#fff;height:24px;margin-bottom:24px;display:inline-block;}
  #flip div:first-child {animation: show 10s linear infinite;}
  @keyframes show {
  0% {margin-top:-144px;}
  5% {margin-top:-96px;}
  33% {margin-top:-96px;}
  38% {margin-top:-48px;}
  66% {margin-top:-48px;}
  76% {margin-top:0px;}
  100% {margin-top:0px;}}
  #flipper p {position:fixed;color:#999; }
  </style>
  <div style='float: left'>Ha Rpi4:&nbsp;&nbsp;</div>
  <div id=flipper><div id=flip><div><div>
  {{states('sensor.dark_sky_summary')}}</div></div><div><div>
  Daily -  {{states('sensor.dark_sky_daily_summary')}}</div></div><div><div>
  Hourly - {{states('sensor.dark_sky_hourly_summary')}}</div></div><div><div>
  {{states('sensor.dark_sky_summary')}}</div></div><div><div>
  {{states('sensor.dark_sky_summary')}}</div></div><div><div>
#  {{states('sensor.br_symbol')}}</div></div><div><div>
## all default
#disabled_mode: false
kiosk_mode: >-
  {{ is_state('input_select.mode','Kiosk') }}

#"{{ states('input_select.mode') =='Kiosk'}}"

compact_mode: true
shadow: true
footer_mode: false
split_mode: true
#disable_sidebar: false
#hide_header: false
#hide_help: false
#hide_unused: false
#hide_refresh: false
hide_config: true
#hide_raw: false

# https://maykar.github.io/custom-header/#configuration/buttons
#menu_hide: false
#voice_hide: false
#options_hide: false
#menu_dropdown: false
#voice_dropdown: false
#reverse_button_direction: false
#button_icons:

button_text:
  options: >-
    {{ time }} - <ha-icon icon='{{states('sensor.weather_icon')}}' style='vertical-align: middle';></ha-icon> - {{states('sensor.temp_current') }}°

show_tabs: >
  {% if not is_state('input_select.mode','Developer') %}0 to 21, 26 to 28
  {% else %} 0 to 28
  {% endif %}

# https://maykar.github.io/custom-header/#configuration/exceptions
exceptions:
  - conditions:
      user: Gezin, (redacted list of Names 1-6)
    config:
      show_tabs: 0 to 3,6,15 to 18
      voice_hide: true
      options_hide: true
  - conditions:
      user_agent: iPhone
    config:
      footer_mode: true
      indicator_top: false
      header_text: >-
        {% set alerts = namespace(active=[], color='var(--google-red-500)') %}
        {% set inside=states('sensor.temperatuur_living')%}
        {% set outside=states('sensor.temp_current')%} 
        {% set temp_color='var(--primary-text-color)'%} 
        {% set symbol='°C' %}
        {% if states('sensor.weatheralerts') | float != 0 %}
          {% for alert in state_attr('sensor.weatheralerts', 'alerts') %}
          {% set alerts.active = alerts.active + [alert['title']] %}
          {% endfor %}
        {% else %} {% set alerts.active = alerts.active + ['No active alerts'] %}
        {% endif %}
        <div style='display: flex;display: -webkit-flex;'>
        <div>Ha&nbspRpi4:&nbsp;&nbsp;</div>
        <marquee>
        <span style='color: {{ temp_color }}'>
        Inside temperature: {{ inside }}{{ symbol }},
        Outside temperature: {{ outside }}{{ symbol }},
        </span>
        <span style='color: {{ alerts.color }};'>
        Alerts: {{ alerts.active | join(' - ')}},
        </span>
        <span style='color: {{ temp_color }}'>
        Summary - {{states('sensor.dark_sky_summary')}},
        Daily -  {{states('sensor.dark_sky_daily_summary').split('.')[0]}},
        Hourly - {{states('sensor.dark_sky_hourly_summary').split('.')[0]}}.
        </span>
        </marquee>
#        Ha Rpi4:
#        {% set alerts = namespace(active=[], color="var(--google-red-500)") %}
#        {% set temperature = namespace(inside=states('sensor.temperatuur_living'), outside=states('sensor.temp_current'), color="var(--primary-text-color)", symbol="°C") %}
#        {% if states('sensor.weatheralerts') | float != 0 %}
#        {% for alert in state_attr('sensor.weatheralerts', 'alerts') %}
#        {% set alerts.active = alerts.active + [alert['title']] %}
#        {% endfor %}
#        {% else %}
#        {% set alerts.active = alerts.active + ['No active alerts'] %}
#        {% endif %}
#        <marquee>
#        <span style='color: {{ temperature.color }}'>
#            Inside temperature: {{ temperature.inside }}{{ temperature.symbol }}
#            Outside temperature: {{ temperature.outside }}{{ temperature.symbol }}
#        </span>
#        <span style='color: {{ alerts.color }}; margin-left: 10px;'>
#            Alerts: {{ alerts.active | join('  -  ')}}
#        </span>
#        <span style='color: {{ temperature.color }}'>
#        {{states('sensor.dark_sky_summary')}}
#          Daily -  {{states('sensor.dark_sky_daily_summary')}}
#          Hourly - {{states('sensor.dark_sky_hourly_summary')}}
#        </span>
#        </marquee>

      menu_hide: true
#      voice_hide: false
      options_hide: true
  - conditions:
      user_agent: iPad
    config:
      menu_hide: true
#      voice_hide: false
      options_hide: true

# https://maykar.github.io/custom-header/#configuration/tabs
#chevrons: true
indicator_top: true
#default_tab:
#reverse_tab_direction: false
#hide_tabs: An array or comma separated string of tabs to hide, more info below
#show_tabs: An array or comma separated string of tabs to hide, more info below
#hidden_tab_redirect: true

tab_icons:
  alarm: >-
    {{states('sensor.alarm_panel_icon')}}
  phones_tablets: >-
    {{states('sensor.presence_icon')}}
  weer_klimaat: >-
    {{states('sensor.weather_icon')}}
  alarmclock: >-
    {{'mdi:alarm-off' if is_state('sensor.next_alarm','Not set') else 'mdi:alarm'}}

tabs_color:
  phones_tablets: >-
    {{state_attr('sensor.family_home','icon_color')}}

magic in the works!

Copied your code and its still not working. And I did a full cache refresh aswell.
If I comment out just the header_text the tab_colour, tab_icon, and the button_text starts working properly.

Sorry

Any errors in dev console (F12)?

So, I believe when you had the title text at the very top and then indented the code below it, it rendered those indents as new lines or ‘\n’ which shows as ‘n’, but now you are putting the title below the initial jinja if statements so it will no longer render those indents and I’m sure placing the title in a div helps as well.

Here is the F12 from Chrome v79

OK Got rid of this {{states('sensor.cal_home_event_event')}}</div></div><div><div> and its working i think it does not like the @ symbol…

Try something like this {{ states('sensor.cal_home_event_event') | replace("@","&#64;") }}

I have tried different sensors and the ones causing the problems seem to be the platform template sensors. If that makes sense.

So it’s not just sensors that contain an @ symbol? Did you try the code above that replaces the @ symbol with it’s html code?

Edit: Seems it’s not the @ symbol, looking into it more. Doesn’t seem like the issue is with template sensors either as those seem to be working fine.

i have a problem.
i have instal custom header and logged in with a user that i want only show my home assistant in kioskmode, but now are al the users in kioskmode how can i change it? i am not able to open the gui of custom header and also “?disable_cch” at the end of my url is’nt working