City of Ghent Style Guide

Header

When to use this component

All websites and all pages must include the header.

How it works

The header component is the first visible component on every page. The position of the header is fixed on the page.

Depending on the device’s screen resolution, the header switches to one of the two following modes:

  • Desktop header: Desktop resolutions and tablet in landscape mode
  • Mobile header: Tablet in portrait mode and mobile resolutions

Desktop header

The desktop header is used on desktop resolutions and tablets in landscape mode.

The desktop header can consist of four parts:

  1. Top header with Ghent logo (always required)
  2. Menu with main navigation (optional)
  3. Breadcrumbs (required for most websites)
  4. Header image (optional)

The top header with Ghent logo has the following components:

  • Ghent logo (always required)
  • Site title (optional, only for separate websites)
  • Search (optional, only if applicable)
  • Authentication component (optional, only if applicable)
  • Language switch (optional, only for multilingual websites with synchronous translations)

To get an idea of different combinations for the desktop header, how they look and how they work, see the examples.

Further specific requirements for the City of Ghent website and for separate websites are listed below.

Mobile header

The mobile header is used on tablet in portrait mode and below (mobile resolutions).

The mobile header can consist of three parts, from top to bottom:

  1. Top header with Ghent logo (always required)
  2. Site title (optional, only for separate websites)
  3. Breadcrumbs (required for most websites)
  4. Header image (optional)

The top header has the following components:

  • Ghent logo (always required)
  • Search button with link (optional, only if applicable)
  • Authentication component (optional, only if applicable)
  • Menu button (optional, only if applicable)
  • Language switch (optional, only if applicable and for multilingual websites with synchronous translations)

For the top header of the mobile header, the following conditions apply:

  1. Where there is a header image, the header image in the mobile header can be shown or not shown. See the examples.

  2. When the website has a search function, the search function is always shown in the header.

  3. When the website has main navigation, the menu button is always shown in the header. The menu button opens the mobile menu with the main navigation.

  4. When the website has main navigation and also the authentication component and/or a language switch, the authentication component and/or the language switch are integrated in the menu. In these cases, the menu button is always shown in the header. The menu button opens the mobile menu with the main navigation and the authentication component and/or the language switch. In other words: whenever the website has main navigation, the menu button is used and the authentication component and/or the language switch (if applicable) are integrated in the mobile menu.

  5. When the website has no main navigation, but has a search function and the authentication component and a language switch, the menu button is used and the authentication component and the language switch are integrated in the menu. The search button is always shown in the header.

Taking the above conditions into account, only the following combinations of elements are possible in the top part of the mobile header:

  • Ghent logo + Search button + Menu button
  • Ghent logo + Search button + Language switch
  • Ghent logo + Search button + Authentication component
  • Ghent logo + Search button
  • Ghent logo + Authentication component
  • Ghent logo + Language switch
  • Ghent logo + Menu button
  • Ghent logo + Authentication component + Language switch
  • Ghent logo only

To get an idea of different combinations for the mobile header, how they look and how they work, see the examples.

Further specific requirements for the City of Ghent website and for separate websites are listed below.

Requirements

City of Ghent website

  • The desktop header includes the following elements:
    • Top header with Ghent logo, Search and authentication component
    • Breadcrumbs
    • Header image (optional)
    • The Ghent logo links to the homepage of the City of Ghent general website.
  • The mobile header includes the following elements:
    • Top header with Ghent loco, Search button and authentication component
    • Breadcrumbs
    • Header image (optional, can be shown or not shown independently from the desktop header)
  • The first item of the breadcrumbs is “Home” and links to the homepage of the City of Ghent general website.
  • The search function searches the content of the whole City of Ghent general website.

Separate websites

  • The combination of the City of Ghent logo with the title of the separate website links to the homepage of the separate website.
  • The first item of the breadcrumbs is “Home” and links to the homepage of the separate website.
  • The search function - if included - only searches the content of the separate website.

Further documentation

Authentication component

For websites that where users can authenticate themselves, the authentication component is included in the header.

  • When the user is not authenticated, the authentication component presents a login link. See the examples.
  • When the user is authenticated, the authentication component shows the user name of the user to indicate that the user is authenticated. In this case, the authentication component acts as a drop-down user-menu that includes links to the profile of the user (if applicable) and a logout link. See the examples.

The authentication component does not provide authentication itself but it is a way to make accessible authentication for the user and show the authentication status of the user.

The authentication mechanism can be anything from a magic link, to authentication using a user name and password, to strong authentication. The authentication mechanism that is used depends on the functional needs and requirements of the website itself.

Language switch

For multilingual websites with synchronous translations, the language switch is included in the header. The language switch shows the current language and is a drop-down menu to let the user switch to another language. In the drop-down menu, the current language is shown first (as a label, not a link). After that, the other language in which the current page is available are shown. These other languages are shown as links that each link to the current page in those specific languages. See the examples.

Header image

The header can include a header image When included, the header image is always shown on desktop and tablet resolutions. The header image can have an optional caption tag. On mobile resolutions, the header image can be shown or not shown. This is a functional decision specific for the website or even for certain web pages within a website. The optional caption for the header image is never shown in the mobile header. See the examples.

{% set hasMenu = menu or (search and auth and translate) %}

<header class="header{{ hasMenu ? ' header--menu' : '' }}">
  <div class="content-container">
    {% include '@logo' with {
      site_name: site_name,
      type: subsite ? 'subsite'  : ''
    } %}

    {% if search %}
      {% include '@link' with {
        link: "#",
        text: "search",
        modifier: "search--link",
        title: "search"
      } %}

      {% include '@search' with {
        label: header_search_label,
        search_id: _self.name ~ '-header-search',
        placeholder: header_search_placeholder,
        modifier_search: header_search_modifier_search,
        text: header_search_text,
        modifier_submit: header_search_modifier_submit
      } %}
    {% endif %}

    {% if auth %}
      {% include '@authentication' with {
        id: _self.name ~ '-authentication',
        items: mijn_gent_block_items,
        auth: mijn_gent_block_auth,
        image: mijn_gent_block_image,
        accordion: true
      } %}
    {% endif %}

    {% if translate %}
      {% include '@language-switcher' with {
        accordion: true,
        id: _self.name ~ '-translate'
      } %}
    {% endif %}

    {% if hasMenu %}

      {% set Auth %}
        {% if auth %}
          {% include '@authentication' with {
            id: _self.name ~ '-authentication-mobile',
            items: mijn_gent_block_items,
            auth: mijn_gent_block_auth,
            image: mijn_gent_block_image,
            accordion: false
          } %}
        {% endif %}
      {% endset %}

      {% set Translate %}
        {% if translate %}
          {% include '@language-switcher' with {
            accordion: false,
            id: _self.name ~ '-translate-mobile'
          } %}
        {% endif %}
      {% endset %}

      {% include '@main-menu' with {
        items: menu_items,
        auth: Auth,
        translate: Translate,
        id: _self.name ~ '-menu',
      } %}

    {% endif %}
  </div>

  {% if subsite %}
    <div class="site-name">
      <span>{{ site_name }}</span>
    </div>
  {% endif %}

  {% include '@breadcrumbs' with {
    items: breadcrumbs_items,
    id: _self.name ~ '-header-crumbs'
  } %}

  <hr/>
  {% if hero_image_src %}
    <figure class="hero{{ mobile_hero ? ' hero--mobile' : '' }}">
      {% if theme %}
        <div class="theme{{ theme_light ? ' theme--light' : '' }}">
          <div class="theme-title">
            {% include '@image' with {
              'src': (theme_light ? figure_logo_src_dark : figure_logo_src_light) | path,
              'alt_text': figure_logo_alt_text,
              'modifier': null,
              'ratio': null
            } %}
            {% if theme_title %}
            {% include '@heading' with {
              'type': 'h1',
              'heading_text': hero_title
            } %}
            {% endif %}
          </div>
        </div>
      {% endif %}
      {% include '@image' with {
        'src': hero_image_src,
        'alt_text': '',
        'ratio': '4:1'
      } %}
      {% if hero_image_description %}
        {% include '@figcaption' with {
          'figcaption': hero_image_description
        } %}
      {% endif %}
    </figure>
  {% endif %}
</header>
<header class="header">
    <div class="content-container">
        <a href="#" title="Home" class="site-logo " rel="home">
            Stad Gent
        </a>

        <a href='#' class="search--link" title="search">
            search </a>

        <form class="form search">
            <label for="theme_no-hero_auth-header-search">Search
            </label>

            <input type="search" id="theme_no-hero_auth-header-search" name="theme_no-hero_auth-header-search" class="search" placeholder="Search" required="true" />
            <input type="submit" value="Search" class="" />
        </form>

        <div class="authentication accordion">

            <button aria-expanded="false" aria-controls="theme_no-hero_auth-authentication" class="toggle accordion--button">
                <span class="avatar">j</span>
                <span>Webteam1_VOORNAAM DG_ACHTERNAAM</span>
            </button>

            <div id="theme_no-hero_auth-authentication" class="accordion--content" aria-hidden="true" hidden>
                <article class="content">
                    <h2>Mijn bibliotheek</h2>
                    <section class="profile">
                        <span class="avatar">j</span>
                        <div class="profile-info">
                            <span>Webteam1_VOORNAAM DG_ACHTERNAAM</span>
                            <a href='#' class="button button-primary button-small">
                                Show profile </a>
                        </div>
                    </section>
                    <section>

                        <ul class="links">
                            <li><a href='javascript:(void);'>Overzicht</a></li>
                            <li><a href='javascript:(void);'>Leestips</a></li>
                        </ul>

                    </section>
                    <section>
                        <h2>Mijn gent</h2>

                        <ul class="links">
                            <li><a href='javascript:(void);'>Mijn profiel</a></li>
                            <li><a href='javascript:(void);'>Nieuwsbrieven</a></li>
                            <li><a href='javascript:(void);'>Historiek</a></li>
                        </ul>

                    </section>
                    <footer>
                        <a href='javascript:(void);' class="button button-small button-secondary">
                            Afmelden </a>
                    </footer>
                </article>

            </div>

        </div>

    </div>

    <nav class="breadcrumb section--default" aria-labelledby="theme_no-hero_auth-header-crumbs">
        <div class="content-container">
            <h2 id="theme_no-hero_auth-header-crumbs" class="visually-hidden">Breadcrumb</h2>
            <ol class="no-style">
                <li><a href='#'>Home</a></li>
                <li><a href='#'>Society, Welfare & health</a></li>
                <li><a href='#'>News & Events</a></li>
                <li><span>Page title</span></li>
            </ol>
        </div>
    </nav>

    <hr />
</header>
{
  "mijn_gent_block_items": [
    "<a href='javascript:(void);'>Mijn profiel</a>",
    "<a href='javascript:(void);'>Nieuwsbrieven</a>",
    "<a href='javascript:(void);'>Historiek</a>"
  ],
  "auth": true,
  "search": true,
  "translate": false,
  "mijn_gent_block_auth": true,
  "header_search_id": "header-search",
  "header_search_label": "Search",
  "header_search_placeholder": "Search",
  "header_search_text": "Search",
  "breadcrumbs_id": "system-breadcrumb",
  "breadcrumbs_items": [
    "<a href='#'>Home</a>",
    "<a href='#'>Society, Welfare & health</a>",
    "<a href='#'>News & Events</a>",
    "<span>Page title</span>"
  ],
  "hero_image_src": null,
  "hero_image_description": "Caption text comes here.",
  "hero_title": "ICT Supplier <span>District 09</span>",
  "figure_logo_src_dark": "/styleguide/img/stock/district09-dark.svg",
  "figure_logo_src_light": "/styleguide/img/stock/district09-light.svg",
  "site_name": "Stad Gent",
  "menu_items": [],
  "mijn_gent_block_image": false,
  "theme": true
}
  • Content:
    @use "sass:math";
    
    header.header {
      position: relative;
      margin-bottom: .3rem;
      padding: .3rem 0;
    
      // first row
      > .content-container {
        display: flex;
        align-items: center;
    
        @include tablet {
          flex-wrap: wrap;
        }
    
        > :not(:first-child) {
          margin-left: gutter();
        }
    
        .site-logo {
          margin-right: auto;
    
          &.subsite {
            flex: 1;
          }
        }
    
        .search {
          display: none;
          flex: 1;
          flex-wrap: nowrap;
          justify-content: flex-end;
    
          label {
            @extend %visually-hidden;
            @include bold-text;
          }
    
          input {
            margin-bottom: 0;
          }
    
          input[type=submit] {
            max-width: 0;
            padding: 0;
            transition: opacity .2s ease-in-out, max-width .2s ease-in-out, padding .2s ease-in-out;
            box-shadow: none;
            opacity: 0;
    
            &:focus {
              max-width: 9999px;
              margin-left: .4rem;
              padding: 0 1rem;
              opacity: 1;
            }
          }
    
          input[type=search],
          input[type=text] {
            flex: 0 1 auto;
            width: 100%;
            min-width: 0;
            max-width: 210px;
            margin-right: 0;
            transition: max-width .2s ease-in-out;
    
            &:invalid {
              box-shadow: none;
            }
    
            &:focus,
            &:valid {
              max-width: 440px;
              margin: 0 0 0 .4rem;
    
              ~ input[type=submit] {
                max-width: 9999px;
                margin-left: .4rem;
                padding: 0 1rem;
                opacity: 1;
              }
    
            }
          }
    
          @include tablet {
            display: flex;
          }
        }
    
        .search--link {
          @include theme('background-color', 'color-primary--lighten-5', 'header-search-background-color');
    
          display: block;
          min-width: 2.4rem;
          max-width: calc(.8rem + 32px);
          height: 2.4rem;
          border-bottom: 0;
          border-radius: border-radius('radius-1');
          background: svg-as-background('search', color('dark-gray'), 32, 32) no-repeat left .4rem center;
          text-indent: -9999px;
          overflow: hidden;
    
          @include tablet {
            display: none;
          }
        }
    
        .authentication {
          align-items: center;
          margin-left: .8rem;
    
          @include tablet {
            margin-left: gutter();
          }
        }
    
        .authentication,
        .language-switcher {
          align-self: stretch;
        }
    
        // Align main menu with site logo and breadcrumb.
        nav.menu {
          @include tablet {
            flex-basis: 100%;
            flex-grow: 1;
            order: 9999;
            margin-left: 0;
          }
    
          line-height: 1;
        }
      }
    
      .site-name {
        @include theme('color', 'color-tertiary', 'default-text-color');
        @include bold-text;
    
        @include tablet {
          display: none;
        }
    
        margin: .8rem 0 .4rem;
        font-size: .9rem;
      }
    
      nav.breadcrumb {
        margin-top: .4rem;
      }
    
      hr {
        $span: percentage(math.div(2, 12));
    
        position: relative;
        max-width: $bp-max-content;
        margin-top: .3rem;
        margin-bottom: 2.3rem;
        border: 0;
        overflow: visible;
    
        &::before,
        &::after {
          @include theme('border-color', 'color-primary--lighten-4', 'header-border-bottom');
    
          position: absolute;
          top: 100%;
          width: 100%;
          height: 1rem;
          margin-top: .3rem;
          border-top: 2px solid;
          content: '';
        }
    
        &::before {
          left: -$gutter-width;
          width: 3rem + $gutter-width;
          border-right: 2px solid;
          border-top-right-radius: border-radius('radius-4');
    
          @include desktop {
            left: 0;
            width: calc(#{$span} + 2rem);
          }
        }
    
        &::after {
          right: -$gutter-width;
          width: calc(100% - 3rem + 2px + #{$gutter-width});
          border-left: 2px solid;
          border-top-left-radius: border-radius('radius-4');
    
          @include desktop {
            right: 0;
            width: calc(100% - #{$span} - 2rem + 2px);
          }
        }
      }
    
      // Hero image, overlaps and hides breadcrumb accolade.
      figure.hero {
        $span: percentage(math.div(2, 12));
    
        display: none;
        position: relative;
        min-height: 1.6rem;
        // Give the image 1px margin relative to the container
        // so the accolade can overlap the edges
        // IE error fix
        margin: -1.7rem calc(-1rem + 1px) .3rem;
    
        @include tablet {
          display: block;
        }
    
        &.hero--mobile {
          display: block;
    
          &::before,
          &::after {
            content: '';
          }
    
          .image-wrapper,
          img {
            display: block;
          }
        }
    
        .theme {
          display: none;
          position: absolute;
          top: 0;
          right: 0;
          align-items: center;
          justify-content: center;
          width: 100%;
          height: 100%;
          margin: 0;
          padding: $gutter-width 2rem;
          text-align: center;
          z-index: z('hero', 'base');
    
          @include tablet {
            display: flex;
            width: span(4 wide of 12);
            max-width: 23rem;
            height: calc(100% - 1.6rem + 1px); // 1px to fix rendering issues
          }
    
          @include desktop {
            padding: 0 2rem;
          }
    
          @media (min-width: $bp-max-content) {
            right: calc((100% - #{$bp-max-content}) / 2);
          }
    
          &::before,
          &::after {
            @include theme('background-color', 'color-primary', 'hero-background-color');
            @include theme('border-color', 'color-primary', 'hero-background-color');
            position: absolute;
            left: 0;
            width: 100%;
            height: auto;
            border: 1px solid;
            content: '';
            opacity: .94;
            z-index: z('hero', 'overlay');
          }
    
          &.theme--light {
            &::before,
            &::after {
              @include theme('background-color', 'color-primary--lighten-5', 'hero-background-light-color');
              @include theme('border-color', 'color-primary--lighten-5', 'hero-background-light-color');
              opacity: 1;
            }
    
            h1 {
              @include theme('color', 'color-tertiary', 'hero-light-text-color');
            }
          }
    
          &::before {
            top: 0;
            bottom: 50%;
            border-bottom-left-radius: border-radius('radius-5');
          }
    
          &::after {
            top: 50%;
            bottom: 0;
            border-top-left-radius: border-radius('radius-5');
          }
    
          .theme-title {
            display: flex;
            flex-direction: column;
            justify-content: center;
            width: 100%;
            min-height: 100%;
          }
    
          img {
            display: inline-block;
            width: auto;
            height: 3rem;
            margin-bottom: 1rem;
    
            @include desktop {
              height: 4rem;
            }
    
            @media (min-width: $bp-max-content) {
              height: 5rem;
            }
          }
    
          figure:last-child {
            display: flex;
            flex: .6 1 auto;
            flex-direction: column;
    
            img {
              flex: 1 1 auto;
              margin-bottom: 0;
            }
          }
    
          h1 {
            @include theme('color', 'color-secondary', 'hero-text-color');
    
            margin: 0;
            font-size: 1.2rem;
    
            @include desktop {
              font-size: 1.6rem;
            }
    
            @media (min-width: $bp-max-content) {
              font-size: 2rem;
            }
    
            span {
              display: block;
              font-size: .9rem;
    
              @include desktop {
                font-size: 1.2rem;
              }
    
              @media (min-width: $bp-max-content) {
                font-size: 1.5rem;
              }
            }
          }
        }
    
        .image-wrapper {
          display: none;
    
          @include tablet {
            display: block;
          }
        }
    
        img {
          display: none;
    
          @include tablet {
            display: block;
          }
        }
    
        figcaption {
          @extend %content-container;
          display: none;
          right: 0;
          width: auto;
    
          @include tablet {
            display: block;
            position: absolute;
            top: calc(100% - 1.6rem);
            left: 3rem + $gutter-width;
            margin: 0;
            padding: .4rem $gutter-width 0;
            z-index: z('hero', 'caption');
          }
    
          @include desktop {
            left: calc(#{$span} + 2rem);
          }
    
          @media (min-width: $bp-max-content) {
            right: calc((100% - #{$bp-max-content}) / 2);
            left: calc(#{$span} + 2rem + (100% - #{$bp-max-content}) / 2);
            padding-right: 0;
          }
        }
    
        &::before,
        &::after {
          position: absolute;
          bottom: -.1rem;
          height: 1rem;
          background-color: color('white');
          content: none;
          z-index: z('hero', 'accolade');
    
          @include tablet {
            height: 1.7rem;
            content: '';
          }
        }
    
        &::before {
          left: 0;
          width: 4rem;
          border-top-right-radius: border-radius('radius-3');
    
          @include tablet {
            width: 3rem + $gutter-width;
            border-top-right-radius: border-radius('radius-5');
          }
    
          @include desktop {
            width: calc(#{$span} + 2rem);
          }
    
          @media (min-width: $bp-max-content) {
            width: calc(#{$span} + 2rem + ((100% - #{$bp-max-content}) / 2));
          }
        }
    
        &::after {
          right: 0;
          left: 4rem;
          width: auto;
          border-top-left-radius: border-radius('radius-3');
    
          @include tablet {
            left: 3rem + $gutter-width;
            border-top-left-radius: border-radius('radius-5');
          }
    
          @include desktop {
            left: calc(#{$span} + 2rem);
          }
    
          @media (min-width: $bp-max-content) {
            // Make sure it overlaps the image edges.
            // IE error fix
            right: -1px;
            left: calc(#{$span} + 2rem + ((100% - #{$bp-max-content}) / 2));
          }
        }
    
        &:not(.hero--subsite) .theme ~ figcaption {
          left: 0;
          width: 100%;
          max-width: none;
          background-color: color('white');
    
          @media (min-width: $bp-max-content) {
            width: auto;
          }
        }
    
        &--subsite {
          &::before,
          &::after {
            width: 100%;
          }
        }
      }
    
      &--menu > .content-container {
        > .authentication,
        > .language-switcher {
          @include tablet-and-below {
            display: none;
          }
        }
      }
    }
    
  • URL: /components/raw/header/_header.scss
  • Filesystem Path: components/41-organisms/header/_header.scss
  • Size: 10 KB