Vissza a webes elemekhez
Űrlapok

Kapcsolatfelvételi űrlap – interaktív

Élő előnézet – a komponens teljes méretben.

Élő előnézet
HTML · CSS · JS
HTML
<section class="we-contact">
    <div class="we-contact__intro">
        <span class="we-contact__eyebrow">KAPCSOLAT</span>
        <h2>Írj nekünk!</h2>
        <p>Kérdésed van? Töltsd ki az alábbi űrlapot, és próbáld ki a működését.</p>
    </div>

    <form class="we-contact__form" novalidate>
        <div class="we-contact__field">
            <label for="we-contact-name">Teljes név</label>
            <input
                type="text"
                id="we-contact-name"
                name="name"
                placeholder="Add meg a neved"
                autocomplete="name"
                aria-describedby="we-contact-name-error"
            />
            <span class="we-contact__error" id="we-contact-name-error"></span>
        </div>

        <div class="we-contact__field">
            <label for="we-contact-email">E-mail-cím</label>
            <input
                type="email"
                id="we-contact-email"
                name="email"
                placeholder="pelda@email.hu"
                autocomplete="email"
                aria-describedby="we-contact-email-error"
            />
            <span class="we-contact__error" id="we-contact-email-error"></span>
        </div>

        <div class="we-contact__field">
            <label for="we-contact-message">Üzenet</label>
            <textarea
                id="we-contact-message"
                name="message"
                rows="5"
                placeholder="Írd ide az üzeneted..."
                aria-describedby="we-contact-message-error"
            ></textarea>
            <span class="we-contact__error" id="we-contact-message-error"></span>
        </div>

        <button class="we-contact__submit" type="submit">
            <span>Űrlap ellenőrzése</span>
            <span aria-hidden="true">→</span>
        </button>

        <p class="we-contact__success" role="status" hidden>
            Az ellenőrzés sikeres! Minden mezőt helyesen töltöttél ki.
        </p>

        <p class="we-contact__note">
            Ez egy tesztűrlap. Az üzenet nem kerül elküldésre.
        </p>
    </form>
</section>
CSS
.we-contact {
    --wc-accent: #55d6a0;
    --wc-text: #edf5f1;
    --wc-muted: #a1b0a9;
    --wc-border: rgba(163, 194, 177, 0.2);

    width: 100%;
    max-width: 680px;
    margin: 0 auto;
    padding: 42px;
    color: var(--wc-text);
    background: #111a18;
    border: 1px solid var(--wc-border);
    border-radius: 20px;
    font-family: Inter, Arial, sans-serif;
    box-sizing: border-box;
}

.we-contact *,
.we-contact *::before,
.we-contact *::after {
    box-sizing: border-box;
}

.we-contact__intro {
    margin-bottom: 32px;
}

.we-contact__eyebrow {
    display: inline-block;
    margin-bottom: 12px;
    color: var(--wc-accent);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 2px;
}

.we-contact__intro h2 {
    margin: 0 0 12px;
    color: var(--wc-text);
    font-size: clamp(28px, 4vw, 38px);
    font-weight: 600;
    letter-spacing: -1px;
    line-height: 1.2;
}

.we-contact__intro p {
    margin: 0;
    color: var(--wc-muted);
    font-size: 14px;
    line-height: 1.8;
}

.we-contact__form {
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.we-contact__field {
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.we-contact__field label {
    color: var(--wc-text);
    font-size: 13px;
    font-weight: 600;
}

.we-contact__field input,
.we-contact__field textarea {
    width: 100%;
    min-width: 0;
    padding: 14px 16px;
    border: 1px solid var(--wc-border);
    border-radius: 10px;
    outline: none;
    background: #17231f;
    color: var(--wc-text);
    font-family: inherit;
    font-size: 14px;
    line-height: 1.6;
    transition: border-color 0.2s ease,
                box-shadow 0.2s ease;
}

.we-contact__field input::placeholder,
.we-contact__field textarea::placeholder {
    color: #788980;
}

.we-contact__field input:focus,
.we-contact__field textarea:focus {
    border-color: var(--wc-accent);
    box-shadow: 0 0 0 3px rgba(85, 214, 160, 0.1);
}

.we-contact__field textarea {
    min-height: 130px;
    resize: vertical;
}

.we-contact__field .we-contact__invalid {
    border-color: #ff8585;
}

.we-contact__error {
    color: #ff9999;
    font-size: 12px;
    line-height: 1.5;
}

.we-contact__error:empty {
    display: none;
}

.we-contact__submit {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    width: 100%;
    margin-top: 2px;
    padding: 15px 22px;
    border: 1px solid var(--wc-accent);
    border-radius: 10px;
    background: var(--wc-accent);
    color: #102019;
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.2s ease,
                transform 0.2s ease;
}

.we-contact__submit:hover {
    background: #78e5b6;
    transform: translateY(-2px);
}

.we-contact__submit:focus-visible {
    outline: 2px solid var(--wc-text);
    outline-offset: 4px;
}

.we-contact__submit span:last-child {
    font-size: 20px;
    font-weight: 400;
}

.we-contact__success {
    margin: 0;
    padding: 15px 17px;
    border: 1px solid rgba(85, 214, 160, 0.35);
    border-radius: 10px;
    background: rgba(85, 214, 160, 0.08);
    color: var(--wc-accent);
    font-size: 13px;
    line-height: 1.7;
}

.we-contact__success[hidden] {
    display: none;
}

.we-contact__note {
    margin: -8px 0 0;
    color: var(--wc-muted);
    font-size: 11px;
    line-height: 1.7;
    text-align: center;
}

@media (max-width: 520px) {
    .we-contact {
        padding: 28px 20px;
        border-radius: 14px;
    }

    .we-contact__intro {
        margin-bottom: 26px;
    }

    .we-contact__form {
        gap: 19px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .we-contact__field input,
    .we-contact__field textarea,
    .we-contact__submit {
        transition: none;
    }

    .we-contact__submit:hover {
        transform: none;
    }
}
JavaScript
(function () {
    "use strict";

    function initContactForms() {
        const forms = document.querySelectorAll(".we-contact__form");

        forms.forEach(function (form) {
            if (form.dataset.initialized === "true") {
                return;
            }

            form.dataset.initialized = "true";

            const fields = [
                {
                    input: form.querySelector('[name="name"]'),
                    error: form.querySelector("#we-contact-name-error"),
                    message: "Kérjük, add meg a neved."
                },
                {
                    input: form.querySelector('[name="email"]'),
                    error: form.querySelector("#we-contact-email-error"),
                    message: "Adj meg egy érvényes e-mail-címet."
                },
                {
                    input: form.querySelector('[name="message"]'),
                    error: form.querySelector("#we-contact-message-error"),
                    message: "Kérjük, írd meg az üzeneted."
                }
            ];

            const success = form.querySelector(".we-contact__success");

            function validateField(field) {
                const input = field.input;
                const value = input.value.trim();
                let message = "";

                if (!value) {
                    message = field.message;
                } else if (
                    input.name === "email" &&
                    !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
                ) {
                    message = "Kérjük, érvényes e-mail-címet adj meg.";
                }

                field.error.textContent = message;
                input.classList.toggle(
                    "we-contact__invalid",
                    Boolean(message)
                );
                input.setAttribute(
                    "aria-invalid",
                    String(Boolean(message))
                );

                return !message;
            }

            fields.forEach(function (field) {
                field.input.addEventListener("input", function () {
                    validateField(field);

                    if (success) {
                        success.hidden = true;
                    }
                });
            });

            form.addEventListener("submit", function (event) {
                event.preventDefault();

                if (success) {
                    success.hidden = true;
                }

                let firstInvalid = null;
                let isValid = true;

                fields.forEach(function (field) {
                    if (!validateField(field)) {
                        isValid = false;

                        if (!firstInvalid) {
                            firstInvalid = field.input;
                        }
                    }
                });

                if (!isValid) {
                    if (firstInvalid) {
                        firstInvalid.focus();
                    }

                    return;
                }

                if (success) {
                    success.hidden = false;
                }
            });
        });
    }

    if (document.readyState === "loading") {
        document.addEventListener("DOMContentLoaded", initContactForms);
    } else {
        initContactForms();
    }
})();