City of Ghent Style Guide

Input

When to use this component

Use the input component to let users enter text or a value that is not longer than a single line.

When not to use this component

Do not use the input component to let users enter longer text that might have multiple lines. In this case, use textarea component instead.

How it works

Types of input

  • Default (simple text or text value that is not longer than a single line, no format)
  • Date (date format)
  • Time
  • Number (number format)
  • Password (password, characters are masked)
  • Email (automatically validated)
  • Telephone number

Date input

To let users enter a date, use the input type date. This will trigger the built-in browser date picker functionality for a consistent user experience. It is also the best way to let the user enter a date on mobile and it is accessible (most custom date pickers aren’t).

For browsers that do not support the input type date, make sure there is a fallback, for instance, by adding a field message explaining the date format that should be used combined with pattern validation.

Usage, behaviour, layout and validation

The input component is a form element that should always be used in a form. For a description of the usage, the behavior, the layout and validation of form elements, see the form component examples and documentation.

Input

{% set describedBy = null %}
{% if field_description %}
  {% set describedBy = id ~ "-description" %}
{% endif %}
{% if field_message %}
  {% set describedBy = id ~ "-message" %}
{% endif %}
<div class="form-item {{ modifier ? ' ' ~ modifier : '' }}{{ stacked ? ' stacked' : '' }}">
  {% include '@form-label' with {
    "label": label,
    "for": id,
    "label_optional": label_optional
  } %}
  {% include '@field-message' with {
    "field_message": field_description,
    "modifier": null,
    "id": id ~ "-description"
  } %}

  <div class="form-columns">
    <div class="form-item-column">
      {% include '@'~input_component with {
        "id": id,
        "name": name|default(id),
        "ariaDescribedBy": describedBy,
        "type": type,
        "invalid": modifier == 'error',
        "modifier": modifier
      }%}
    </div>
    {% apply spaceless %}
    <div class="form-item-column">
      {% if field_message %}
        {% include '@field-message' with {
          "modifier": modifier,
          "id": id ~ "-message"
        } %}
      {% endif %}
    </div>
    {% endapply %}
  </div>
</div>
<!-- Default -->
<div class="form-item ">
      <label for="input_id">input-text
          <span class="label-optional">
              Optional
          </span>
      </label>
      <div class="field-message " id="input_id-description">
          Optional field description.<br> --- <br> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium consectetur eveniet illo porro quis sint.
          <div class="accolade "></div>
      </div>

      <div class="form-columns">
          <div class="form-item-column">

              <input type="text" id="input_id" aria-describedby="input_id-description" name="input_id" class="text" />
          </div>
          <div class="form-item-column"></div>
      </div>
  </div>

<!-- With Error -->
<div class="form-item  error">
      <label for="input_text--error">input-text
          <span class="label-optional">
              Optional
          </span>
      </label>

      <div class="form-columns">
          <div class="form-item-column">

              <input type="text" id="input_text--error" aria-describedby="input_text--error-message" name="input_text--error" class="text error" aria-invalid="true" />
          </div>
          <div class="form-item-column">
              <div class="field-message error" role="alert" id="input_text--error-message">
                  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec laoreet, urna sit amet convallis rhoncus, felis ex.
                  <div class="accolade "></div>
              </div>
          </div>
      </div>
  </div>

<!-- With Success -->
<div class="form-item  success">
      <label for="input-text--success">input-text
          <span class="label-optional">
              Optional
          </span>
      </label>

      <div class="form-columns">
          <div class="form-item-column">

              <input type="text" id="input-text--success" aria-describedby="input-text--success-message" name="input-text--success" class="text success" />
          </div>
          <div class="form-item-column">
              <div class="field-message success" role="alert" id="input-text--success-message">
                  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec laoreet, urna sit amet convallis rhoncus, felis ex.
                  <div class="accolade "></div>
              </div>
          </div>
      </div>
  </div>

<!-- Date -->
<div class="form-item ">
    <label for="input-date">input-date
        <span class="label-optional">
            Optional
        </span>
    </label>

    <div class="form-columns">
        <div class="form-item-column">

            <input type="date" id="input-date" name="input-date" class="date" />
        </div>
        <div class="form-item-column"></div>
    </div>
</div>

<!-- Email -->
<div class="form-item ">
    <label for="input-email">input-email
        <span class="label-optional">
            Optional
        </span>
    </label>

    <div class="form-columns">
        <div class="form-item-column">

            <input type="email" id="input-email" name="input-email" class="email" />
        </div>
        <div class="form-item-column"></div>
    </div>
</div>

<!-- Number -->
<div class="form-item ">
    <label for="input-number">input-number
        <span class="label-optional">
            Optional
        </span>
    </label>

    <div class="form-columns">
        <div class="form-item-column">

            <input type="number" id="input-number" name="input-number" class="number" />
        </div>
        <div class="form-item-column"></div>
    </div>
</div>

<!-- Password -->
<div class="form-item ">
    <label for="input-password">input-password
        <span class="label-optional">
            Optional
        </span>
    </label>

    <div class="form-columns">
        <div class="form-item-column">

            <input type="password" id="input-password" name="input-password" class="password" />
        </div>
        <div class="form-item-column"></div>
    </div>
</div>

<!-- Tel -->
<div class="form-item ">
    <label for="input-tel">input-tel
        <span class="label-optional">
            Optional
        </span>
    </label>

    <div class="form-columns">
        <div class="form-item-column">

            <input type="tel" id="input-tel" name="input-tel" class="tel" />
        </div>
        <div class="form-item-column"></div>
    </div>
</div>

<!-- Disabled -->
<div class="form-item ">
    <label for="input--disabled">disabled
        <span class="label-optional">
            Optional
        </span>
    </label>

    <div class="form-columns">
        <div class="form-item-column">

            <input type="text" id="input--disabled" name="input--disabled" class="text" disabled="disabled" />
        </div>
        <div class="form-item-column"></div>
    </div>
</div>

<!-- File -->
<div class="form-item ">
    <label for="input-file">input--file
        <span class="label-optional">
            Optional
        </span>
    </label>

    <div class="form-columns">
        <div class="form-item-column">
            <div class="file" data-file="No file chosen">

                <input type="file" id="input-file" aria-describedby="input-file-description" name="input-file" />

                <span id="input-file-description" class="file__button">Select your files here to upload</span>
            </div>

        </div>
        <div class="form-item-column"></div>
    </div>
</div>

/* Default */
{
  "label": "input-text",
  "id": "input_id",
  "label_optional": "Optional",
  "field_description": "Optional field description.<br> --- <br> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium consectetur eveniet illo porro quis sint.",
  "field_message": null,
  "input_component": "input",
  "type": "text"
}

/* With Error */
{
  "label": "input-text",
  "id": "input_text--error",
  "label_optional": "Optional",
  "field_description": null,
  "field_message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec laoreet, urna sit amet convallis rhoncus, felis ex.",
  "input_component": "input",
  "type": "text",
  "modifier": "error"
}

/* With Success */
{
  "label": "input-text",
  "id": "input-text--success",
  "label_optional": "Optional",
  "field_description": null,
  "field_message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec laoreet, urna sit amet convallis rhoncus, felis ex.",
  "input_component": "input",
  "type": "text",
  "modifier": "success"
}

/* Date */
{
  "label": "input-date",
  "id": "input-date",
  "label_optional": "Optional",
  "field_description": null,
  "field_message": null,
  "input_component": "input",
  "type": "date"
}

/* Email */
{
  "label": "input-email",
  "id": "input-email",
  "label_optional": "Optional",
  "field_description": null,
  "field_message": null,
  "input_component": "input",
  "type": "email"
}

/* Number */
{
  "label": "input-number",
  "id": "input-number",
  "label_optional": "Optional",
  "field_description": null,
  "field_message": null,
  "input_component": "input",
  "type": "number"
}

/* Password */
{
  "label": "input-password",
  "id": "input-password",
  "label_optional": "Optional",
  "field_description": null,
  "field_message": null,
  "input_component": "input",
  "type": "password"
}

/* Tel */
{
  "label": "input-tel",
  "id": "input-tel",
  "label_optional": "Optional",
  "field_description": null,
  "field_message": null,
  "input_component": "input",
  "type": "tel"
}

/* Disabled */
{
  "label": "disabled",
  "id": "input--disabled",
  "label_optional": "Optional",
  "field_description": null,
  "field_message": null,
  "input_component": "input",
  "type": "text",
  "disabled": true
}

/* File */
{
  "label": "input--file",
  "id": "input-file",
  "label_optional": "Optional",
  "field_description": null,
  "field_message": null,
  "input_component": "file",
  "type": "text"
}

  • Content:
    .form-item {
      margin-bottom: 30px;
    
      > * {
        max-width: 410px;
      }
    
      @include desktop {
        > * {
          max-width: 820px;
        }
    
        > .field-message,
        > label {
          max-width: 410px;
        }
      }
    
      &.webform-document-file,
      &.webform-image-file {
        a,
        .file-type {
          display: inline-block;
          margin-bottom: 10px;
          font-size: .7rem;
        }
      }
    
      .field-prefix,
      .field-suffix {
        display: block;
      }
    
      .field-message:not(.error):not(.success) {
        margin-bottom: 20px;
      }
    
      &:not(.stacked) {
        .form-label {
          @include desktop {
            width: 50%;
            max-width: 410px;
          }
        }
    
        .form-columns {
          margin-bottom: 0;
    
          @include desktop {
            display: flex;
    
            .form-item-column {
              width: 50%;
    
              &:last-child {
                display: flex;
                align-items: flex-start;
    
                .field-message {
                  margin: 0 0 $gutter-width * .5 6px;
                  padding: 14px 24px 14px 78px;
    
                  &::before {
                    top: 10px;
                    left: 34px;
                  }
    
                  .accolade {
                    right: auto;
                    bottom: 0;
                    left: 0;
                    width: 20px;
                    height: 100%;
                    transform: rotate(0deg);
    
                    &::before,
                    &::after {
                      width: 20px;
                      border: 0;
                    }
    
                    &::before {
                      top: 0;
                      bottom: 24px;
                      height: 24px;
                      border-radius: 0 0 border-radius("radius-4");
                    }
    
                    &::after {
                      top: 24px;
                      right: 0;
                      bottom: -1px;
                      height: calc(100% - 20px);
                      border-radius: 0 border-radius("radius-4") 0 0;
                    }
                  }
                }
              }
    
              &:empty {
                display: none;
              }
    
              &:not(:empty) {
                width: 100%;
              }
            }
          }
        }
      }
    
      &.stacked {
        > * {
          max-width: none;
        }
    
        .form-columns {
          flex-wrap: wrap;
          margin-top: auto;
        }
    
        .form-columns .form-item-column {
          width: 100%;
          max-width: 800px;
    
          &:empty {
            display: none;
          }
    
          .field-message {
            width: 100%;
            margin-top: 4px;
            margin-left: 0;
          }
        }
      }
    }
    
    .form-item-column {
      .form-item {
        .form-label {
          width: 100%;
        }
      }
    }
    
  • URL: /components/raw/form-item/_form-item.scss
  • Filesystem Path: components/31-molecules/form-item/_form-item.scss
  • Size: 2.5 KB