Krok 6 z 10

Formuláře

📖 Lekce

HTML formuláře

Formuláře jsou způsob, jakým uživatelé posílají data na webové stránce. Používají se pro přihlášení, kontakt, vyhledávání...

<form>
  <input type="text" placeholder="Jmeno">
  <input type="email" placeholder="E-mail">
  <button type="submit">Odeslat</button>
</form>

Typy vstupních polí

  • type="text" - Běžný text
  • type="email" - E-mailová adresa (s validací)
  • type="password" - Heslo (skryté znaky)
  • type="number" - Číslo
  • type="tel" - Telefon
  • type="checkbox" - Zaškrtávací políčko
  • <textarea> - Víceřádkový text
  • <select> - Výběr z možností

Validace pomocí JavaScriptu

Validace = ověření, že uživatel vyplnil formulář správně, ještě před odesláním.

if (email.value === "") {
  showError("Vyplňte e-mail!");
}

Moderní webové stránky validují v reálném čase - hned jak uživatel něco napíše.

V dnešním příkladu uvidíš formulář, který validuje každé pole živě a ukazuje úspěch animací!
💻 Příklad k vyzkoušení
index.php
🚀 Vyzkoušej na Vibmy
<!DOCTYPE html>
<html lang="cs">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Kontaktní formulář</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }

        body {
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            font-family: "Segoe UI", system-ui, sans-serif;
            background: linear-gradient(135deg, #0f0c29, #1a1a3e, #0f2027);
            padding: 2rem;
        }

        .form-container {
            width: 100%;
            max-width: 500px;
            background: rgba(255,255,255,0.04);
            border: 1px solid rgba(255,255,255,0.08);
            border-radius: 24px;
            padding: 3rem;
            backdrop-filter: blur(10px);
        }

        h1 {
            text-align: center;
            font-size: 2rem;
            background: linear-gradient(to right, #00d4aa, #7b68ee);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            margin-bottom: 0.5rem;
        }

        .subtitle {
            text-align: center;
            color: #6b7280;
            margin-bottom: 2rem;
        }

        .form-group {
            margin-bottom: 1.5rem;
            position: relative;
        }

        label {
            display: block;
            color: #a0a0b0;
            font-size: 0.85rem;
            margin-bottom: 0.5rem;
            font-weight: 600;
            letter-spacing: 0.5px;
            text-transform: uppercase;
        }

        input, textarea, select {
            width: 100%;
            padding: 0.9rem 1rem;
            background: rgba(255,255,255,0.06);
            border: 2px solid rgba(255,255,255,0.1);
            border-radius: 12px;
            color: #e0e0e0;
            font-size: 1rem;
            font-family: inherit;
            transition: all 0.3s;
            outline: none;
        }

        input:focus, textarea:focus, select:focus {
            border-color: #7b68ee;
            box-shadow: 0 0 0 4px rgba(123,104,238,0.15);
        }

        input.valid, textarea.valid {
            border-color: #00d4aa;
        }

        input.invalid, textarea.invalid {
            border-color: #ff6b9d;
        }

        .validation-msg {
            font-size: 0.8rem;
            margin-top: 0.4rem;
            display: none;
        }

        .validation-msg.show { display: block; }
        .validation-msg.error { color: #ff6b9d; }
        .validation-msg.success { color: #00d4aa; }

        .check-icon {
            position: absolute;
            right: 12px;
            top: 38px;
            font-size: 1.2rem;
            opacity: 0;
            transition: opacity 0.3s;
        }

        .check-icon.show { opacity: 1; }

        textarea { min-height: 120px; resize: vertical; }

        select option { background: #1a1a3e; }

        .checkbox-group {
            display: flex;
            align-items: center;
            gap: 0.8rem;
        }

        .checkbox-group input[type="checkbox"] {
            width: 20px;
            height: 20px;
            accent-color: #00d4aa;
        }

        .checkbox-group label {
            text-transform: none;
            font-weight: normal;
            font-size: 0.9rem;
            margin: 0;
        }

        .submit-btn {
            width: 100%;
            padding: 1rem;
            background: linear-gradient(135deg, #00d4aa, #7b68ee);
            color: white;
            border: none;
            border-radius: 12px;
            font-size: 1.1rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
            margin-top: 1rem;
        }

        .submit-btn:hover:not(:disabled) {
            transform: translateY(-2px);
            box-shadow: 0 8px 25px rgba(0,212,170,0.4);
        }

        .submit-btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }

        /* Animace úspěchu */
        .success-overlay {
            display: none;
            position: fixed;
            top: 0; left: 0; right: 0; bottom: 0;
            background: rgba(10,10,26,0.95);
            z-index: 100;
            align-items: center;
            justify-content: center;
            flex-direction: column;
        }

        .success-overlay.show { display: flex; }

        .success-check {
            width: 100px;
            height: 100px;
            border-radius: 50%;
            background: linear-gradient(135deg, #00d4aa, #00b4d8);
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 3rem;
            animation: popIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
            margin-bottom: 1.5rem;
        }

        .success-text {
            color: white;
            font-size: 1.5rem;
            font-weight: 600;
            animation: fadeUp 0.5s ease 0.3s both;
        }

        .success-sub {
            color: #8892a4;
            margin-top: 0.5rem;
            animation: fadeUp 0.5s ease 0.5s both;
        }

        .success-btn {
            margin-top: 2rem;
            padding: 0.8rem 2rem;
            background: rgba(0,212,170,0.2);
            border: 1px solid rgba(0,212,170,0.3);
            color: #00d4aa;
            border-radius: 12px;
            font-size: 1rem;
            cursor: pointer;
            animation: fadeUp 0.5s ease 0.7s both;
            transition: all 0.3s;
        }

        .success-btn:hover { background: rgba(0,212,170,0.3); }

        @keyframes popIn {
            0% { transform: scale(0); }
            100% { transform: scale(1); }
        }

        @keyframes fadeUp {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }
    </style>
</head>
<body>
    <div class="form-container">
        <h1>&#x1F4E8; Napište nám</h1>
        <p class="subtitle">Vyplňte formulář a my se vám ozveme</p>

        <form id="contactForm" onsubmit="return handleSubmit(event)">
            <div class="form-group">
                <label>Jméno</label>
                <input type="text" id="name" placeholder="Vaše jméno" oninput="validateField(this, 'name')">
                <span class="check-icon" id="name-check"></span>
                <div class="validation-msg" id="name-msg"></div>
            </div>

            <div class="form-group">
                <label>E-mail</label>
                <input type="email" id="email" placeholder="vas@email.cz" oninput="validateField(this, 'email')">
                <span class="check-icon" id="email-check"></span>
                <div class="validation-msg" id="email-msg"></div>
            </div>

            <div class="form-group">
                <label>Téma</label>
                <select id="subject">
                    <option value="">-- Vyberte --</option>
                    <option>Obecný dotaz</option>
                    <option>Spolupráce</option>
                    <option>Technická podpora</option>
                    <option>Jiné</option>
                </select>
            </div>

            <div class="form-group">
                <label>Zpráva</label>
                <textarea id="message" placeholder="Vaše zpráva..." oninput="validateField(this, 'message')"></textarea>
                <span class="check-icon" id="message-check"></span>
                <div class="validation-msg" id="message-msg"></div>
            </div>

            <div class="form-group">
                <div class="checkbox-group">
                    <input type="checkbox" id="agree">
                    <label for="agree">Souhlasím se zpracováním osobních údajů</label>
                </div>
            </div>

            <button type="submit" class="submit-btn" id="submitBtn">&#x1F4E4; Odeslat zprávu</button>
        </form>
    </div>

    <div class="success-overlay" id="successOverlay">
        <div class="success-check">&#x2714;&#xFE0F;</div>
        <div class="success-text">Zpráva odeslána!</div>
        <div class="success-sub">Děkujeme, ozveme se vám co nejdříve.</div>
        <button class="success-btn" onclick="resetForm()">Odeslat další</button>
    </div>

    <script>
        function validateField(input, type) {
            const msg = document.getElementById(type + "-msg");
            const check = document.getElementById(type + "-check");
            let valid = false;
            let message = "";

            if (type === "name") {
                if (input.value.length === 0) { message = ""; }
                else if (input.value.length < 2) { message = "Jméno musí mít alespoň 2 znaky"; }
                else { valid = true; message = "Výborně!"; }
            }

            if (type === "email") {
                const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
                if (input.value.length === 0) { message = ""; }
                else if (!emailRegex.test(input.value)) { message = "Zadejte platný e-mail"; }
                else { valid = true; message = "Email v pořádku!"; }
            }

            if (type === "message") {
                if (input.value.length === 0) { message = ""; }
                else if (input.value.length < 10) { message = "Zpráva je příliš krátká (min. 10 znaků)"; }
                else { valid = true; message = "Díky za zprávu!"; }
            }

            input.classList.remove("valid", "invalid");
            if (input.value.length > 0) input.classList.add(valid ? "valid" : "invalid");

            msg.textContent = message;
            msg.className = "validation-msg" + (message ? " show " + (valid ? "success" : "error") : "");
            check.textContent = valid ? "&#x2705;" : "";
            check.className = "check-icon" + (valid ? " show" : "");
        }

        function handleSubmit(e) {
            e.preventDefault();

            const name = document.getElementById("name");
            const email = document.getElementById("email");
            const message = document.getElementById("message");
            const agree = document.getElementById("agree");

            validateField(name, "name");
            validateField(email, "email");
            validateField(message, "message");

            if (!name.classList.contains("valid") || !email.classList.contains("valid") || !message.classList.contains("valid")) {
                return false;
            }

            if (!agree.checked) {
                alert("Prosím, odsouhlaste zpracování údajů.");
                return false;
            }

            document.getElementById("successOverlay").classList.add("show");
            return false;
        }

        function resetForm() {
            document.getElementById("contactForm").reset();
            document.querySelectorAll("input, textarea").forEach(el => el.classList.remove("valid", "invalid"));
            document.querySelectorAll(".validation-msg").forEach(el => el.classList.remove("show"));
            document.querySelectorAll(".check-icon").forEach(el => el.classList.remove("show"));
            document.getElementById("successOverlay").classList.remove("show");
        }
    </script>
</body>
</html>
← Zpět 6 / 10 Další krok →