HTML Buttons for the ESP web server

Hello and welcome to our contribution today.


After yesterday it was about HTML and square brackets, today we want to look at what you can implement with a little HTML and a small script.

For this we need the following components:

A microcontroller with an ESP8266 chip such as the Amica V2
A relay module such as our 2-relay module
A DC-DC Step-Up Module, as the Amica only delivers 3.3V, but our relay requires 5V
A breadboard with jumper cable, such as our popular Set

Of course, you can also supply the relay module directly with a 5V, and save the step-up module. This makes more sense for a finished project in a housing, as the Amica can also be supplied with the same power supply.

How to use and set the step-up module we have already in our blog post "MT3608 Step-Up DC-DC Voltage Regulator" described.

We connect the components as follows:

Amica V2























The last post discussed how we connect the ESP to an existing Wi-Fi network, and how we answer a request from the browser, including the output of a small HTML file.

I mentioned in some HTML tags that these since HTML5 should no longer be used. In modern websites, the design is often realized by means of cascading style sheets (CSS).

Before everyone runs away with the fear that a CSS course is coming, it should be mentioned that it is possible to design beautiful buttons, texts, sliders and forms using CSS.

If you search for "css buttons" in Google image search, some examples will appear.

Now it's about implementation - what code do we upload to our ESP?

As a basis, we take the code from the tutorial of adjust the code:



 Rui Santos
 Complete project details at  

We download the WiFi library already known to us
#include <ESP8266WiFi.H>

Here we enter the WLAN name (SSID) and the zugans key
Const Char* Ssid     = "MyFritzBox";
Const Char* Password = "MyWIWlanKey";

We set the web server to port 80
WiFiServer Server(80);

A variable to store the HTTP request
String Header;

Here the current status of the relay is recorded
String output5State = "off";
String output4State = "off";

The gPIO pins used
D1 = GPIO5 and D2 = GPIO4 - just search google for "Amica Pinout"  
Const Int output5 = 5;
Const Int output4 = 4;

Void Setup() {   Serial.Begin(115200);   Define the defined GPIO pins as output ...   pinMode(output5, Output);   pinMode(output4, Output);   // ... and first set to LOW   digitalWrite(output5, Low);   digitalWrite(output4, Low);   Connect to the network via Wi-Fi   Serial.Print("Connecting to ");   Serial.println(Ssid);   Wifi.Begin(Ssid, Password);   while (Wifi.Status() != WL_CONNECTED) {     Delay(500);     Serial.Print(".");   }   Output the IP from the web server to the serial monitor   Serial.println("");   Serial.println("Wi-Fi connected.");   Serial.println("IP Address: ");   Serial.println(Wifi.localIP());   Server.Begin();

Void Loop(){   WiFiClient Client = Server.available();   Listens to requests from clients   If (Client) {                             If a new client connects,     Serial.println("New Client.");          Output to the serial monitor     String currentLine = "";                create a string with the incoming data from the client     while (Client.Connected()) {            repeat as long as the client is connected       If (Client.available()) {             Case a byte for reading is there,         Char C = Client.Read();             read the byte, and then         Serial.Write(C);                    on the serial monitor.         Header += C;         If (C == 'n') {                    if the byte is a new line Char           if the current line is empty, 2 came in sequence.           this is the end of the HTTP request from the client, so we'll send a response:           If (currentLine.length() == 0) {             HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)             followed by the content type so that the client knows what follows, followed by a blank line:             Client.println("HTTP/1.1 200 OK");             Client.println("Content-type:text/html");             Client.println("Connection: close");             Client.println();                          Here the GPIO pins are switched on or off             If (Header.Indexof("GET /5/on") >= 0) {               Serial.println("GPIO 5 on");               output5State = "on";               digitalWrite(output5, High);             } else If (Header.Indexof("GET /5/off") >= 0) {               Serial.println("GPIO 5 off");               output5State = "off";               digitalWrite(output5, Low);             } else If (Header.Indexof("GET /4/on") >= 0) {               Serial.println("GPIO 4 on");               output4State = "on";               digitalWrite(output4, High);             } else If (Header.Indexof("GET /4/off") >= 0) {               Serial.println("GPIO 4 off");               output4State = "off";               digitalWrite(output4, Low);             }                          The HTML page is now displayed here:             Client.println("<! DOCTYPE html><html>");             Client.println("<head><meta name="viewport"" content="width=device-width, initial-scale=1">");             Client.println("<link rel="icon"" href="data:,">");             Follow the CSS code to design the on/off buttons             Here you can adjust the background color (background-color) and font size (font-size)             Client.println("<style>html - font-family: Helvetica; display: inline block; margin: 0px auto; text-align: center;");             Client.println(".button - background-color: #333344; border: none; color: white; padding: 16px 40px;");             Client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;");             Client.println(".button2 "background-color: #888899; </style></head>");                          Website heading             Client.println("<body><h1>ESP8266 Web Server</h1>");                          Show the current status, and AN/OFF Buttons for GPIO 5               Client.println("<p>GPIO 5 - State " + output5State + "</p>");             if output5State = off, show the ON button                    If (output5State=="off") {               Client.println("<p><a href="/5/on"><button class="button">On</button></a></p>");             } else {               Client.println("<p><a href="/5/off"><button class="button button2">OFF</button></a></p>");             }                              The same for GPIO 4             Client.println("<p>GPIO 4 - State " + output4State + "</p>");             If output4State = off, show the ON button                    If (output4State=="off") {               Client.println("<p><a href="/4/on"><button class="button">On</button></a></p>");             } else {               Client.println("<p><a href="/4/off"><button class="button button2">OFF</button></a></p>");             }             Client.println("</body></html>");                          The HTTP response ends with a blank line             Client.println();             and we leave the loop with a break             Break;           } else { if a new row comes, delete the current row             currentLine = "";           }         } else If (C != 'A'r') {  if something comes that is not a line break,           currentLine += C;      attach it to the end of currentLine         }       }     }     Delete the header variable for the next pass     Header = "";     Closing the connection     Client.Stop();     Serial.println("Client Disconnected.");     Serial.println("");   }

We load the code on our Amica, and open the Serial Monitor in the Arduino IDE:


Next, we enter the IP address of the server in the browser, e.g. on the mobile phone. (Attention, the PC or smartphone must be connected to the same network as the ESP).


Now we can easily switch the relays from the smartphone (or PC).



And if you look around the internet, you can also find nicer buttons, such as these:


The HTML code and the CSS code for these buttons are available at


I hope this article has given you an insight into the possibilities of the ESP web server.

If you liked this post, I would be pleased to receive a short feedback. Just write to us if you would be interested in the topic SVG for displaying bars and small vector graphics with the ESP web server.

I wish you a lot of fun recreating and say goodbye to the next article.


Esp-8266Projects for advanced users


Andreas Wolter

Andreas Wolter

@Thomas Schultz: ab Zeile 60
if (client.available()) {
beginnt die aktualisierung der Webseite. Mein Vorschlag wäre, die Bedingung durch ein ODER zu erweitern, damit auf die Inputs reagiert werden kann. Folglich müsste man vorher die Inputs auslesen und falls sich diese geändert haben, müsste man dann in die Bedingung diese Änderung einbringen. Als Beispiel:
int inputA_new = 0;
int inputA_old = 0;

inputA_new = digitalRead(EINGANG);
if (client.available() || inputA_new != inputA_old) {
//zeige Werte aus Input A
inputA_old = inputA_new;

für zwei Eingänge wäre das dann wie folgt:
int inputA_new = 0;
int inputA_old = 0;
int inputB_new = 0;
int inputB_old = 0;

inputA_new = digitalRead(EINGANG_A);
inputB_new = digitalRead(EINGANG_B);
if (client.available() || inputA_new != inputA_old || inputB_new != inputB_old) {
//zeige Werte aus Input A
//zeige Werte aus Input B
inputA_old = inputA_new;
inputB_old = inputB_new;

@Georg: etwas spät, aber: der AsynchWebserver ist anders gelöst. eventuell hilft Ihnen das weiter:

Thomas Schultz

Thomas Schultz

Hallo und vielen Dank für dieses schöne Beispiel.
Ich habe es mal direkt für mein aktuelles Project benutzt.
Ich habe nur ein kleine Problem, zusätzlich würde ich gerne noch zwei
Kontaktausgänge eines anderen Moduls auslesen. Das auslesen ist kein
Problem, auch das anzeigen nicht… aber die Webseite wird im vorliegenden
ja nur bei Änderungen eines Relais neu aufgebaut.
Wie kann ich das auch mit zwei INPUTS bewerkstelligen?

Für entsprechende Hilfe wäre ich sehr dankbar

Phil Phras

Phil Phras

Ich bin bei der IdeenSuche für eins meiner Projekte auf diesen Blog gestoßen und bin begeistert!
Ich habe auch in anderen Blogs hier gestöbert und möchte ein großes Lob aussprechen.

Hier werde ich StammLeser :-) Und wenn ich mal wieder eins meiner Projekte veröffentliche geb ich auf jeden Fall diese Seite hier an als Ideen- und CodeQuelle an.

Vielen Dank



das thema ist inzwischen recht alt :-( , für mich aber noch aktuell…
habe versucht den code mit einem asyncwebserver zu kombinieren (die verwendung dieser art des webservers lässt sich aus anderen gründen nicht mehr ändern) – beim compileren wurde die kombination unter anderem mit – ‘class AsyncWebServer’ has no member named ‘available’ – quitiert…
Was kann ich da machen?

Thmas Nimpsch

Thmas Nimpsch

Hallo ,
Vielen Dank für dieses Beispiel, genau danach hab ich gesucht.
Thomas Nimpsch



Schalter die sich automatisch aktualisieren währen nicht schlecht.

Sprich wenn ich von mehreren Geräten auf die Webseite zugreife. Zum Beispiel schalte ich mit dem Smartphone Kanal 1 ein, wird auf dem PC automatisch angezeigt das der Schalter 1 auch ein ist.

Oder das wenn ich per Taster Kanal 1 ein schalte, das auch auf der Webseite automatisch angezeigt wird das der Kanal 1 eingeschaltet ist.

Bisher muss man immer die Webseite neuladen, z.B. mit F5 um das aktuelle Ergebniss zu sehen.



an Herbert.

Versuche doch den Taster mal mit einem Interrupt aus.
Ich hoffe ich darf hier einen Link posten, wenn nicht:
Herbert suche mal auf deiner Suchmaschine deines Vertrauens nach: ESP8266 External Interrupt.



Toller Beitrag, soweit funktioniert auch alles.
Mein Problem ist das ich zusätzlich noch einen Hardware Taster einbauen wollte.
Der aber nicht funktioniert wenn der Client mit dem ESP8266 verbunden ist.
Ich vermute das Problem ist die while (client.connected() funktion. Die verhindert das auf die Tastereingabe parrallel zur Verbindung eines Client funktioniert.

Gibt es dafür eine Lösung? Und warum benötigt man eigentlich die while?



Hallo Markus,
wäre es möglich noch einen Slider zu integrieren, mit Bsp. Sketch?

K. Dobler

K. Dobler

Hallo Markus,
dein Beispiel hat mir sehr geholfen.
Mit ihm habe ich des geschafft mein Garagentor vom Handy aus zu steuern.
Jetzt geht es nur noch um kleine Anpassungen und Verschönerungen.

Vielen Dank
Kurt Dobler

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN