Form Field, lable animation

Form Field, lable animation

Erwecke deine Formulare zum Leben! Mit eleganten Animationen tanzen Labels und Formularfelder harmonisch über den Bildschirm, um deinen Benutzern ein fesselndes und raffiniertes Erlebnis zu bieten.

Eine Rails-Anwendung

Zunächst setzen wir eine Rails-Anwendung auf, inklusive der Implementierung eines Benutzerobjekts.
$ rails new FormField
$ cd FormField
$ rails g scaffold User anrede name vorname email plz ort strasse lebenslauf:text agb:boolean
$ rails db:migrate
Ich konfiguriere das Grundgerüst mithilfe meines Basiscodes. Und installiere das gem sassc-rails.
// Gemfile

gem "sassc-rails"
Jetzt muss es noch gebundelt werden.
$ bundle install

1.png 640 KB


Lass uns nun mit Stimulus beginnen.
$ rails g stimulus form_field
Unter der connect-Methode tragen wir folgendes ein:
// app/javascript/controllers/form_field_controller.js

connect() {
  this.checkFilledState();
  this.element.addEventListener("focus", this.handleFocus.bind(this));
  this.element.addEventListener("blur", this.handleBlur.bind(this));
}
Die connect-Methode wird aufgerufen, wenn das Element mit dem Controller verbunden ist. In dieser Methode werden folgende Aktionen durchgeführt:
  • checkFilledState(): Überprüft den Anfangszustand des Elements und fügt die CSS-Klasse "is-filled" hinzu, wenn der Wert nicht leer ist und nicht "-1" entspricht.
  • addEventListener: Fügt Event-Listener für "focus" und "blur" hinzu, die die entsprechenden Methoden aufrufen, um die Klasse "is-filled" hinzuzufügen oder zu entfernen.

checkFilledState-Methode:

// app/javascript/controllers/form_field_controller.js

checkFilledState() {
  if (this.element.value.trim() !== "" && this.element.value.trim() !== "-1") {
    this.element.classList.add("is-filled");
  }
}
Überprüft den Anfangszustand des Elements und fügt die Klasse "is-filled" hinzu, wenn der Wert des Elements weder leer noch "-1" ist.

handleFocus- und handleBlur-Methoden:

// app/javascript/controllers/form_field_controller.js

handleFocus() {
  this.element.classList.add("is-filled");
}

handleBlur() {
  if (this.element.value.trim() === "" || this.element.value.trim() === "-1") {
    this.element.classList.remove("is-filled");
  }
}
  • handleFocus: Wird aufgerufen, wenn das Element den Fokus erhält, und fügt die Klasse "is-filled" hinzu.
  • handleBlur: Wird aufgerufen, wenn das Element den Fokus verliert. Entfernt die Klasse "is-filled", wenn der Wert des Elements leer oder "-1" ist.

data-controller das input field

  • Um den code zu aktivieren umschliessen wir mit dem tag data-controller das input field was wir steuern wollen.
  • // app/views/users/_form.html.erb
    
    <div>
      <%= form.label :anrede, style: "display: block" %>
      <%= form.text_field :anrede, "data-controller": "form-field" %>
    </div>
    
    <div>
      <%= form.label :name, style: "display: block" %>
      <%= form.text_field :name, "data-controller": "form-field" %>
    </div>
    
    <div>
      <%= form.label :vorname, style: "display: block" %>
      <%= form.text_field :vorname, "data-controller": "form-field" %>
    </div>
    
    <div>
      <%= form.label :email, style: "display: block" %>
      <%= form.text_field :email, "data-controller": "form-field" %>
    </div>
    
    <div>
      <%= form.label :plz, style: "display: block" %>
      <%= form.text_field :plz, "data-controller": "form-field" %>
    </div>
    
    <div>
      <%= form.label :ort, style: "display: block" %>
      <%= form.text_field :ort, "data-controller": "form-field" %>
    </div>
    
    <div>
      <%= form.label :strasse, style: "display: block" %>
      <%= form.text_field :strasse, "data-controller": "form-field" %>
    </div>
    
    <div>
      <%= form.label :lebenslauf, style: "display: block" %>
      <%= form.text_area :lebenslauf, "data-controller": "form-field" %>
    </div>
    
    <div>
      <%= form.label :agb, style: "display: block" %>
      <%= form.check_box :agb %>
    </div>

Gestaltung

  • Die Funktion ist nun abgeschlossen, und wir können uns nun dem Gestalten widmen.
  • // app/assets/stylesheets/_form.scss
    
    /* Stildefinitionen für das label-Element */
    div { 
      position:relative;
    }
    /* Positionierung und Größe */
    label {
      position: absolute;
      left: calc(0.9375rem + 1.875rem);
      top: calc(50% - 0.125rem);
      cursor: pointer;
      display: block;
    
      /* Textformatierung */
      font-size: 1.125rem;
      -webkit-transform: translateY(-50%);
      transform: translateY(-50%);
    
      /* Übergangseffekte */
      -webkit-transition: font-size 0.35s, -webkit-transform 0.35s;
      transition: font-size 0.35s, all 0.35s;
      transition: all 0.35s, font-size 0.35s;
      transition: all 0.35s, font-size 0.35s, -webkit-transform 0.35s;
    
      /* Verbesserung für 3D-Transformationseffekte */
      -webkit-backface-visibility: hidden;
      backface-visibility: hidden;
    }
  • Nicht erschrecken, momentan sieht es schlimm aus. Wird aber bald besser.
  • // app/assets/stylesheets/_form.scss
    
    .is-filled+label,
    :focus+label {
      left: 0.9375rem;
      font-size: 0.775rem;
      -webkit-transform: translateY(-1.5875rem);
      transform: translateY(-1.5875rem);
    }
    
    textarea+label {
      left: calc(0.9375rem + 1.875rem);
      position: absolute;
      top: 2rem;
    }
  • wir müssen im form partial noch kleine Änderungen vornehmen, das Label unter das Textfeld verschieben.
  • // app/views/users/_form.html.erb
    
    <div>
      <%= form.text_field :anrede, "data-controller": "form-field" %>
      <%= form.label :anrede, style: "display: block" %>
    </div>

Bewegung ins ganze

  • Jetzt können wir sehen das schon etwas Bewegung ins ganze kommt.
  • // app/assets/stylesheets/_form.scss
    
    /* Gemeinsame Erscheinungseinstellungen für verschiedene Browser */
    input[type="text"] {
      -webkit-appearance: none;
      -moz-appearance: none;
      appearance: none;
    
      /* Rand- und Schattenstil */
      border: 2px solid transparent;
      border-radius: 0.25rem;
      box-shadow: rgba(99, 99, 99, 0.2) 0 0.125rem 0.5rem 0;
    
      /* Blockanzeige und Textformatierung */
      display: block;
      font-size: 1.125rem;
      height: 3.75rem;
    
      /* Entfernen des Standard-Browser-Fokusrahmens */
      outline: 0;
    
      /* Innenabstand für Text und Inhalt */
      padding: 0.625rem 1.875rem 0;
    
      /* Übergangseffekte für Hintergrund und Schatten */
      transition: background 0.35s, box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1);
    
      /* Vollständige Definition für Übergangseffekte, um Präfixe zu berücksichtigen */
      -webkit-transition: background 0.35s, -webkit-box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1);
      transition: background 0.35s, box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1);
      -moz-transition: box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1), background 0.35s;
      -o-transition: box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1), background 0.35s;
    
      /* Volle Breite des Containers einnehmen */
      width: calc(100% - 4rem);
      &:focus {
        border: 2px solid #86b7fe;
        box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, .25) !important;
      }
    }
  • Diese CSS-Regeln setzen den Stil für ein Textarea-Element, einschließlich seiner Größe, Schatten, Übergangseffekte und Schriftformatierung. Bei Fokuserhalt (textarea:focus) ändert sich der Schattenstil für visuelles Feedback. Beachten Sie, dass die verwendeten Variablen (wie die Farben) möglicherweise in Ihrem Stylesheet definiert sein müssen.
  • // app/assets/stylesheets/_form.scss
    
    /* Stildefinitionen für das Textarea-Element */
    textarea {
      /* Rand- und Schattenstil */
      border: 2px solid transparent;
      border-radius: 0.25rem;
      box-shadow: rgba(99, 99, 99, 0.2) 0 0.125rem 0.5rem 0;
      /* Blockanzeige und Textformatierung */
      display: block;
      font-family: lato, arial, helvetica, sans-serif;
      font-size: 1.125rem;
      font-style: normal;
      font-weight: 300;
      /* Abmessungen und Innenabstand */
      height: 12.5rem;
      line-height: 1.5;
      padding: 1.25rem 1.875rem 0.625rem;
      /* Verhinderung der Größenänderung durch Benutzer */
      resize: none;
      /* Übergangseffekte für Hintergrund und Schatten */
      transition: background 0.35s, box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1);
      /* Vollständige Definition für Übergangseffekte, um Präfixe zu berücksichtigen */
      -webkit-transition: background 0.35s, -webkit-box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1);
      transition: background 0.35s, box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1);
      -moz-transition: box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1), background 0.35s;
      -o-transition: box-shadow 0.35s cubic-bezier(0.645, 0.045, 0.355, 1), background 0.35s;
      /* Volle Breite des Containers einnehmen */
      width: calc(100% - 4rem);
      &:focus {
        /* Änderung des Schattenstils bei Fokuserhalt */
        border: 2px solid #86b7fe;
        box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, .25) !important;
      }
    }

Select-Feld hinzufügen

  • Wir müssen jetzt noch ein Select-Feld hinzufügen und entsprechend anpassen.
  • // app/assets/stylesheets/_form.scss
    
    /* Stildefinitionen für das Select-Element */
    select {
      /* Entfernung von Standard-Browser-Stilen */
      -webkit-appearance: none;
      background-color: #fff;
      cursor: pointer;
      outline: 0;
      padding-top: 0;
      width: 25%;
    }
    /* Entfernung des Dropdown-Pfeils für Internet Explorer */
    select::-ms-expand {
      display: none;
    }
    /* Anpassung des Fokusrings für Firefox */
    select:-moz-focusring {
      color: transparent;
      text-shadow: 0 0 0 #000;
    }
    .label_select {
      top: 9px;
      left: 16px;
      font-size: 0.775rem;
    }
  • Wir müssen das Label im Teil (Partial) wieder nach oben verschieben, und das Textfeld ersetzen wir durch ein Dropdown-Feld (Select).
  • // app/views/users/_form.html.erb
    
    <div>
      <%= form.label :anrede, style: "display: block", class: "label_select" %>
      <%= form.select :anrede, ["", 'Herr', 'Frau'] %>
    </div>

FontAwesome

  • Die folgenden CSS-Regeln legen das Erscheinungsbild und das Verhalten für Checkboxen fest. Fokuseffekte und Validierungsanzeige sind ebenfalls berücksichtigt. Beachten Sie, dass es eventuell notwendig ist, die Regelnamen (wie label) entsprechend der tatsächlichen Struktur Ihres HTML-Dokuments anzupassen. Im Vorfeld installieren Fontawesome.
  • // Gemfile
    
    gem "font-awesome-sass", "~> 6.5.1"
  • jetzt noch bundle install und in der _form.scss importieren.
  • $ bundle install
  • // app/assets/stylesheets/_form.scss
    
    @import "font-awesome";
    ...

Erscheinungsbild und Verhalten für Checkboxen

  • Diese CSS-Regeln definieren das Erscheinungsbild und Verhalten für Checkboxen und deren Label in verschiedenen Zuständen, einschließlich Fokuseffekten, Hover-Effekten und Validierungsanzeige.
  • // app/assets/stylesheets/_form.scss
    
    /* Stildefinitionen für Checkboxen und deren Label */
    input[type="checkbox"]+label,
    .form-label-radio {
      position: static;
      min-height: 2.25rem;
      padding-left: 3.25rem;
      padding-top: 0.3125rem;
      transform: translateY(0);
      transition: 0.3s;
      z-index: 1;
    }
    /* Stildefinitionen für den Zustand vor dem Fokus/Hover */
    input[type="checkbox"]+label:before,
    .form-label-radio:before {
      border: 0.0625rem solid #ccc;
      box-shadow: 0 0.1875rem 0.375rem rgba(0, 0, 0, 0.16),
        0 0.1875rem 0.375rem rgba(0, 0, 0, 0.23);
      color: #fff;
      display: block;
      height: 2.25rem;
      line-height: 2.25rem;
      transition: 0.3s;
      width: 2.25rem !important;
    }
    /* Stildefinitionen für den Zustand vor dem Fokus/Hover und Pseudo-Element */
    input[type="checkbox"]+label:before {
      content: "\f00c";
      text-size-adjust: 100%;
      display: inline-block;
      font-family: "Font Awesome 6 Free";
      font-style: normal;
      font-variant: normal;
      font-weight: 900;
      margin-right: 0.2em;
      position: relative;
      text-align: center;
      text-decoration: inherit;
      text-transform: none;
      width: 1em;
    }
    /* Positionierung und Darstellung des Pseudo-Elements */
    input[type="checkbox"]+label:before {
      left: 0;
      position: absolute;
      top: 0;
      border-radius: 0.25rem;
    }
    /* Fokuseffekte */
    input[type="checkbox"]:focus+label {
      font-size: 1.125rem;
      transform: translateY(0);
    }
    /* Fokuseffekte auf Pseudo-Elemente */
    input[type="checkbox"]:focus+label:before {
      box-shadow: 0 0.625rem 1.25rem rgba(0, 0, 0, 0.19),
        0 0.375rem 0.375rem rgba(0, 0, 0, 0.23);
    }
    /* Stil für den Zustand "checked" */
    input[type="checkbox"]:checked+label:before {
      color: #009fe3;
    }
    /* Hover-Effekte für den Zustand "unchecked" */
    input[type="checkbox"]:not(:checked)+label:hover:before {
      color: #ccc;
    }
    input[type="checkbox"] {
      position: absolute;
      left: 0.9375rem;
      top: 0.9375rem;
      display: inline-block;
      width: 2.25rem;
      height: 2.25rem;
      margin: 0;
      padding: 0;
      opacity: 0;
      z-index: 0;
    }
    /* Fokuseffekte und Validierung für Checkboxen */
    input[type="checkbox"]:focus:invalid+label {
      color: #a94442;
    }
    input[type="checkbox"]:focus:invalid+label:before {
      background-color: rgba(169, 68, 66, 0.1);
      border-color: #a94442;
    }
    input[type="checkbox"]:focus:invalid+label:after {
      color: rgba(169, 68, 66, 0.1);
    }

CSS-Regeln

  • Diese CSS-Regeln legen das Erscheinungsbild für den Fokus und den ungültigen Zustand eines Texteingabefelds fest. Wenn das Feld den Fokus hat und sich in einem ungültigen Zustand befindet, wird der Hintergrund leicht eingefärbt, der Rand wird rot und es wird ein Schatten hinzugefügt. Das zugehörige Label wird in einer roten Farbe angezeigt.
  • // app/assets/stylesheets/_form.scss
    
    /* Stildefinitionen für den Fokus und ungültigen Zustand eines Texteingabefelds */
    input[type="input"]:focus:invalid {
      background-color: rgba(169, 68, 66, 0.1);
      border-color: #a94442;
      box-shadow: 0 0.3125rem 0.875rem 0 rgba(0, 0, 0, 0.17);
    }
    input[type="input"]:focus:invalid+label {
      color: #a94442;
    }
  • Diese CSS-Regeln legen das Erscheinungsbild für ein Feld mit Fehlern fest. Wenn ein Feld als fehlerhaft markiert ist, wird der Hintergrund leicht eingefärbt, der Rand wird rot, und es wird ein roter Schatten hinzugefügt. Das zugehörige Label wird in einer roten Farbe angezeigt und nach oben verschoben. Damit wir dies erreichen fügen wir eine Prüfung in unser user-Model. Wir überprüfen die eMail auf Richtigkeit und ob Vorname und Name da sind.
  • // app/models/user.rb
    
    class User < ApplicationRecord
      VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d-]+(\.[a-z\d-]+)*\.[a-z]+\z/i
    
      validates :name,  presence: true, length: { maximum: 50 }
      validates :vorname, presence: true, length: { maximum: 50 }
    
      validates :email, presence: true, length: { maximum: 255 },
                        format: { with: VALID_EMAIL_REGEX },
                        uniqueness: { case_sensitive: false }
    end
  • Nun die scss Regeln:
  • // app/assets/stylesheets/_form.scss
    
    .field_with_errors {
      position: static;
      input[type="text"] {
        background-color: rgba(169, 68, 66, 0.1);
        border-color: #a94442;
        box-shadow: 0 0 0 0.25rem rgba(#a94442, .25);
      }
      label {
        position: absolute;
        color: #a94442;
        font-size: 0.775rem;
        left: 0.9375rem;
        -webkit-transform: translateY(-1.5875rem);
        transform: translateY(-1.5875rem);
      }
    }
  • Ergänzen wir noch unsere Pflichtfelder mit required.
  • // app/views/users/_form.html.erb
    
    <div>
      <%= form.text_field :name, "data-controller": "form-field", required: true %>
      <%= form.label :name, style: "display: block" %>
    </div>
    
    <div>
      <%= form.text_field :vorname, "data-controller": "form-field", required: true %>
      <%= form.label :vorname, style: "display: block" %>
    </div>
    
    <div>
      <%= form.text_field :email, "data-controller": "form-field", required: true %>
      <%= form.label :email, style: "display: block" %>
    </div>

Stand der Dinge:


  • 2.png 660 KB


Meld dich an und schreibe ein Kommentar