Lerne Coding
Wie du Placeholder stylen kannst!
11.12.2019

Placeholder stylen, Placeholder emulieren!

Inhaltsverzeichnis
[[TABLE OF CONTENTS]]
access_timeGeschätzte Lesezeit ca. Minuten

Formulare zu stylen kann manchmal schwierig sein, da nicht alle Elemente direkte HTML-Elemente sind und sich somit alle Styles anwenden lassen. In diesem Artikel möchte ich euch die Variante über das Pseudo-Element "placeholder" zeigen, was nur begrenzte Styles zulässt. Eine Alternative dazu ist, ein Plugin zu verwenden.

Ich habe eine JavaScript-Plugin geschrieben, was es ermöglicht, ein Fake-Element automatisiert zu erstellen. So ist man vollkommen frei in der Gestaltung, ähnlich wie beim Stylen von Checkboxen. Leider wird JavaScript benötigt - das sollte in der Regel aber kein Problem darstellen.

Der Internet Explorer unterstützt zum Beispiel gar nicht das Pseudo-Element. Mit meinem Fake-Placeholder-Plugin hast du auch im Internet Explorer die volle Kontrolle über deine Placeholder.

Wie du das Plugin verwenden kannst, erkläre ich dir weiter unten!

Du hast auch Probleme dabei, ein Datei-Upload-Input-Element zu stylen? Dann kann ich dir empfehlen, dir auch mal den folgenden Artikel anzusehen: Wie du Datei-Uploads stylen kannst! 💾

Wie du das Pseudo-Element verwenden kannst

So kannst du bei "normalen" Browsern den Placeholder stylen, über das sogenannte Placeholder-Pseudo-Element. Hier macht es Sinn, über verschiedene Browser-Präfixe zu arbeiten, was bei einem aufwändigeren Styling sicherlich von Nöten ist.

input::placeholder{
    color: red;
    background:pink;
    padding: 10px;
}

input::-ms-input-placeholder{
    color: red;
    background:pink;
    padding: 10px;
}

Was direkt auffällt: Wenn ihr euch den Nachfolgenden Screenshot anschaut, seht ihr, dass die Browser die Einstellungen komplett unterschiedlich interpretieren. Der Placeholder-Selektor ist leider stark den Browsergegebenheiten unterworfen.

Im Edge ist zusätzlich ein extra Präfix von Nöten, um ihn überhaupt angesprochen zu bekommen.

Im Firefox kann man noch über den Browser-Präfix die Opacity ansteuern, im Chrome hingegen wirkt es auch bei opacity: 1; noch so als wäre eine Opacity vorhanden.

input::-moz-placeholder{
    opacity: 1;
}

Mein persönliches Fazit ist, dass sich das Pseudo-Element nur für Basis Styling eignet. Eine zweite Farbe für "Required" zum Beispiel ist unmöglich über das Pseudo-Element umzusetzen.

Aus diesem Grund habe ich ein kleines Plugin geschrieben, welches das Pseudo-Element in ein eigenes HTML-Element wandelt. So ist beim Styling alles möglich, egal, welchen Browser man verwendet.

Eigenes Plugin für das perfekte Styling von Placeholdern

Das Plugin emuliert das Verhalten von Placeholder, darüber ist es möglich, eigene HTML-Elemente anzusprechen. Du kannst ein komplexes Markup aus mehren HTML-Elementen für einen Placeholder hinterlegen. Deinen Gedanken sind keine Grenzen gesetzt.

Zum Beispiel könnt ihr hier keinen Unterschied zwischen den verschiedenen Browsern sehen; von Chrome bis zum Internet Explorer spielen alle mit und legen das gleiche Verhalten an den Tag!

Die einzige Besonderheit ist leider immer noch der Internet Explorer. Dort ist noch ein top-Wert definiert, da er mit Flex an der Stelle nicht gut umgehen konnte. Also ist die Einschränkung nur noch den CSS Eigenheiten der Browser, jedoch keinen Elementen unterlegen.

Placeholder Plugin minimiert Browser Unterschiede
Placeholder Plugin minimiert Browser Unterschiede

Ich habe mich entschieden, für das Plugin eigene Elemente nach validen HTML5 zu verwenden. Vorteil ist hier, dass es keine Gefahr gibt, dass irgendwo schon ein Styling für die Elemente auf der Webseite hinterlegt ist. So ist die Kompatibilität zu deiner bereits bestehenden Webseite viel höher.

Welches HTML-Markup benötigst du?

Die Besonderheiten, die im Vergleich zu einem normalen Formular hinzukommen, sind folgende:

Ein HTML-Tag <placeholder-data-container>: dieses ist zwingend notwendig für die Lauffähigkeit des Plugins. Es darf zwar auch leer sein, muss aber existieren. In diesem Fall werden die normalen Placeholder-Texte einfach in das neue HTML-Element eingesetzt. Wie das ausschaut steht weiter unten. Die placeholder-data-Tags haben immer ein Field Attribute. Bei diesem muss es sich um den Inhalt des Placeholders handeln, da hierüber die Zuordnung des jeweiligen hinzuzufügenden HTML-Templates abläuft. Darüber können nun auch dieselben Markups für diverse Felder geladen werden.

Ich habe die Zuordnung bewusst über das placeholder-Attribute gemacht; im Fall, dass das Plugin eines Tages nicht mehr benötigt wird, sind dann die placeholder-Attribute sauber benannt. In den placeholder-data-Tags seit ihr komplett frei und könnt selbst entscheiden, welches HTML-Markup ihr dort definiert.

<!DOCTYPE html>
<html lang="de">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <link rel="stylesheet" href="main.css">
        <script src="main.js"></script>
    </head>
    <body>
        <form action="/" method="get">
            <label for="Test">Email:</label>
            <input type="email" name="Test" id="Test" placeholder="Email Adresse (Required)">
            <input type="tel" name="Telefon" id="Test34" placeholder="Telefon">

            <input type="tel" name="Telefon" id="Test2">
            <input type="tel" name="Telefon" id="Test3" placeholder="Test">
        </form>

        <placeholder-data-container>

            <placeholder-data field="Email Adresse (Required)">
                Email Adresse <span>(Required)</span>
            </placeholder-data>

            <placeholder-data field="Telefon">
                Telefon <span class="optional">Optional</span>
            </placeholder-data>

        </placeholder-data-container>

    </body>
</html>

Nachdem wir das JavaScript Plugin ausgeführt haben, erstellt das Plugin entsprechend ein eigenes Markup für die Inputfelder. Darüber findet auch das eigene zusätzliche Styling statt. In der main.css stehen zusätzliche Styles; diese werden bei Aufruf des Plugins in den Head inkludiert.

Dieses Markup wird automatisch durch das Plug-in generiert.

<outer-input class="Test placeholder-fake">
    <input type="email" name="Test" id="Test">
    <placeholder-fake>
        Email Adresse <span>(Required)</span>
    </placeholder-fake>
</outer-input>

Bei dem Stylesheet ist wichtig, dass der placeholder-data-container komplett ausgeblendet wird. Der outer-input muss relativ sein, sodass der placeholder-fake dazu absolut positoniert werden kann.

Der placeholder-fake bekommt user-select: none; und pointer-events: none; um durch das Element hindurchklicken zu können. So benötigt dieses Element keinen gesonderten Klick-Handler, um dann den Fokus in den Input zu setzen.

placeholder-data-container{
    display: none!important;
    opacity: 0!important;
}

outer-input{
    display: flex;
    position: relative;
    align-items: center;
}

placeholder-fake{
    position: absolute;
    left: 12px;
    z-index: 10;
    user-select: none;
    pointer-events: none;
    font-family: sans-serif;
    font-size: 20px;
    opacity: 0.6;
}

/* Optional kann angepasst werden bei Bedarf */ 

outer-input.internetExplorer placeholder-fake{
    top: 10px;
}

placeholder-fake span{
    color: red;
}

input{
    padding: 10px;
    width: 290px;
    font-size: 20px;
    font-family: sans-serif;
}

Momentan hat das Plugin noch keine weiteren Optionen für die Konfiguration, diese werde ich nochmal anpassen. Solltest du Vorschläge bezüglich gewünschter oder fehlender Funktionen haben, teile sie gerne in einem Kommentar mit!

Das fertige Plugin (main.css; main.js) findest du Up to Date immer im Github Repository:

Github Logofschuermeyer/placeholderFakeInput
0 0 0

Placeholder Fake JS

Hier noch mal ein lauffähiges Beispiel des Fake-Placeholder-Javascript-Plugins:

placeholder-data-container{
    display: none!important;
    opacity: 0!important;
}

outer-input{
    display: flex;
    position: relative;
    align-items: center;
}

placeholder-fake{
    position: absolute;
    left: 12px;
    z-index: 10;
    user-select: none;
    pointer-events: none;
    font-family: sans-serif;
    font-size: 20px;
    opacity: 0.6;
}

/* Optional kann angepasst werden bei Bedarf */ 

outer-input.internetExplorer placeholder-fake{
    top: 10px;
}

placeholder-fake span{
    color: red;
}

placeholder-fake span.optional{
    font-size: 10px;
}

input{
    padding: 10px;
    width: 290px;
    font-size: 20px;
    font-family: sans-serif;
}

<form action="/" method="get">
  <input type="text" name="Vorname" placeholder="Vorname">
  <input type="text" name="Nachname" placeholder="Nachname">
  <input type="email" name="E-Mail" placeholder="Email Adresse (Required)">
  <input type="tel" name="Telefon" placeholder="Telefon">
</form>

<placeholder-data-container>
  <placeholder-data field="Email Adresse (Required)">
    Email Adresse <span>(Required)</span>
  </placeholder-data>

  <placeholder-data field="Telefon">
    Telefon <span class="optional">Optional</span>
  </placeholder-data>
  
  <placeholder-data field="Vorname">
    Vorname <span class="optional">Optional</span>
  </placeholder-data>

  <placeholder-data field="Nachname">
    Nachname <span class="optional">Optional</span>
  </placeholder-data>
</placeholder-data-container>
document.addEventListener('DOMContentLoaded',function(){
    
    var Placeholder = new PlaceholderFaker();

    Placeholder.getInputsPlaceholder();
    Placeholder.initalEvents();

})

var PlaceholderFaker = function(){

    this.checkInternetExplorer = function(){
        var ua = window.navigator.userAgent;
        var msie = ua.indexOf("MSIE ");
        if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))
        {
           return true;
        }
    }

    this.getInputsPlaceholder = function(){
        var inputs = document.querySelectorAll('input[placeholder]');

        for (let index = 0; index < inputs.length; index++) {
            const field = inputs[index];
            
            if(field.placeholder !== undefined && field.placeholder.length > 0){
                var placeholderTemplate = document.getElementsByTagName('placeholder-data-container')[0].querySelector('placeholder-data[field="'+ field.placeholder +'"]')
                if(placeholderTemplate != undefined){
                    var template = "<placeholder-fake>" + placeholderTemplate.innerHTML + "</placeholder-fake>";
                    field.removeAttribute('placeholder');
                    var htmlInput = field.outerHTML;
                    if(this.checkInternetExplorer()){
                        var fakeField = "<outer-input class='" + field.getAttribute('name') + " placeholder-fake internetExplorer'>" + htmlInput + template + "</outer-input>";  
                    }else{
                        var fakeField = "<outer-input class='" + field.getAttribute('name') + " placeholder-fake'>" + htmlInput + template + "</outer-input>";  
                    }
              
                    field.outerHTML = fakeField;
                }else{
                    var template = "<placeholder-fake>" + field.getAttribute('placeholder') + "</placeholder-fake>";
                    field.removeAttribute('placeholder');

                    if(this.checkInternetExplorer()){
                        field.outerHTML = "<outer-input class='" + field.getAttribute('name') + " placeholder-fake internetExplorer'>" + field.outerHTML + template + "</outer-input>"; 
                    }else{
                        field.outerHTML = "<outer-input class='" + field.getAttribute('name') + " placeholder-fake'>" + field.outerHTML + template + "</outer-input>";
                    }
                }                
            }else{
                if(this.checkInternetExplorer()){
                    field.outerHTML = "<outer-input class='" + field.getAttribute('name') + " placeholder-fake noPlaceholder internetExplorer'>" + field.outerHTML + "</outer-input>";
                }else{
                    field.outerHTML = "<outer-input class='" + field.getAttribute('name') + " placeholder-fake noPlaceholder'>" + field.outerHTML + "</outer-input>";
                }
            }
            

        }

    }

    this.initalEvents = function(){

        var inputs = document.querySelectorAll('outer-input');

        for (let index = 0; index < inputs.length; index++) {
            const input = inputs[index];

            input.getElementsByTagName('input')[0].addEventListener('input',function(e){
               if(this.value.trim().length > 0){
                    this.parentElement.getElementsByTagName('placeholder-fake')[0].style.display = "none";
               }else{
                    this.parentElement.getElementsByTagName('placeholder-fake')[0].style.display = "block";
               }
            })
        }

    }

}
Kommentare zum Artikel
Jannis schreibt ... Kommentar vom 22.11.2022
Top Artikel zum Stylen von Placeholdern

Danke für den Artikel darüber wie man den Placeholder stylen, Placeholder emulieren kann. Ich habe mich sehr gefreut bei https://hellocoding.de/ hereinschauen zu dürfen und halte die genannten Tipps für sehr wertvoll. Dieser Artikel hat mir geholfen, neues Know-how im Bereich "Placeholder styling" zu erwerben.

Antworten
Jannis
Kommentar schreiben

Verwante Beiträge
close