Form Styling Customization

User
<style>
.hub-multistep-btn {
  background-color: #00b4d5;
  border-radius: 25px;
  font-weight: 600;
  min-height: 40px;
  cursor: pointer;
  width: 100%;
  font-size: 15px;
  text-align: center;
  transition: all .3s;
  fill: #fff;
}

#step-progress {
  margin: 20px 0;
  text-align: center;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.step-indicator {
  display: inline-block;
  width: 30px;
  height: 30px;
  line-height: 30px;
  border-radius: 50%;
  background: #ccc;
  color: #000;
  text-align: center;
  margin: 0 5px;
  font-size: 10px;
  font-weight: 600;
  position: relative;
  text-align: center;
}

.step-indicator.active {
  background-color: #00b4d5 !important;
  border-color: #00b4d5 !important;
  color: #a8eeff;
}

.step-head-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  flex: 1;
  position: relative;
}

.step-head-container:not(:last-child)::after {
    content: '';
    position: absolute;
    top: 15px;
    left: 60%;
    right: -40%;
    height: 1px;
    background-color: #babfc5;
    z-index: 0;
}

.step-head-container.completed .step-indicator {
background-color: #000221 !important;
    border: 1px solid #5fdb3a;
    color: #fafafa;
}
.hs_test___letzte_konversion__asset_tag_.hs-test___letzte_konversion__asset_tag_.hs-fieldtype-select.field.hs-form-field {
    display: none !important;
}
.hs-form-field input:not([type=checkbox]), .hs-form-field select, .hs-input.hs-fieldtype-textarea {
    color: #000221;
    font-size: 18px;
    height: 45px;
    transition: border-bottom .2s ease-in-out, background-color .2s ease-in-out, color .2s ease-in-out;
    width: 100% !important;
    background-color: #fff !important;
    border: 1px solid #ccccd3;
    border-radius: 6px !important;
    padding: 10px;
}
.hs_hs_language.hs-hs_language.hs-fieldtype-select.field.hs-form-field {
    display: none !important;
}
.hs-form-private fieldset {
    margin-bottom: 0 !important;
}
.step-buttons {
  margin-top: 30px;
  text-align: center;
  display: flex;
  gap: 12px;
}

.step-buttons button {
  background-color: #00b4d5;
  border: 1px solid #00b4d5;
  border-radius: 25px;
  font-weight: 600;
  min-height: 40px;
  cursor: pointer;
  width: 100%;
  font-size: 15px;
  text-align: center;
  transition: all .3s;
  fill: #fff;
  color: #fff;
}

.step-buttons button#nextBtn:hover {
  background-color: #0092ad !important;
  color: #fff !important;
}

.step-buttons button#backBtn {
  background-color: #fff;
  color: #00b4d5;
  border: 1px solid #00b4d5;
}

.step-buttons button#backBtn:hover {
  background-color: #00b4d5;
  color: #fff;
}

.hs-form-field {
  margin-bottom: 20px;
}

.input-error {
  border-color: red !important;
}

.hs-error-msgs {
  display: block !important;
  color: red;
  font-size: 14px;
  margin-top: 4px;
}

.hs-input[type=checkbox] {
  appearance: none;
  background-color: #fff !important;
  border: 1px solid #717e86;
  border-radius: 4px;
  cursor: pointer;
  height: 30px;
  width: 30px !important;
  transition: background-color .2s ease, border .5s ease;
}

.hs-input[type=checkbox]:checked {
  background-color: #00b4d5 !important;
}

.hs-input[type=checkbox]:checked:after {
  background-color: #00b4d5;
  border-radius: 50%;
  color: #fff;
  content: "✓";
  display: flex;
  border: 1px solid #fff;
  font-size: 11px;
  justify-content: center;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 16px;
  height: 18px;
}

.hs_welche_produkte_wollen_sie_live_sehen_.hs-welche_produkte_wollen_sie_live_sehen_.hs-fieldtype-checkbox.field.hs-form-field label > span:first-child {
  font-size: 14px;
  font-weight: 500;
  line-height: 30px;
  text-align: left;
  color: #33354d;
}

.hs-form-private ul li {
  margin-block: 10px;
}

.hs-form-booleancheckbox label, .hs-form-checkbox label {
  align-items: center;
}
</style>
<script>

</script>
<script>
hbspt.forms.create({
    portalId: "6868748",
    formId: "376e8c84-cbc6-408f-8899-55c2af1436ee",
    target: "#hubspot-form",
    onFormReady: function () {
      const waitForFields = setInterval(() => {
        const form = document.querySelector('#hubspot-form form');
        const allFields = form?.querySelectorAll('.hs-form-field');
        if (!form || !allFields || allFields.length < 5) return;

        clearInterval(waitForFields);

        const stepFields = {
          0: ['welche_produkte_wollen_sie_live_sehen_'],
          1: ['message'],
          2: []
        };

        allFields.forEach(field => {
          const input = field.querySelector('input, select, textarea');
          if (input && input.name && !Object.values(stepFields).flat().includes(input.name)) {
            stepFields[2].push(input.name);
          }
        });

        const stepProgress = document.createElement('div');
        stepProgress.innerHTML = `
          <div id="step-progress">
            <div class="step-head-container"><div class="step-indicator active">1</div><span class="step-label">Produktauswahl</span></div>
            <div class="step-head-container"><div class="step-indicator">2</div><span class="step-label">Anforderungen</span></div>
            <div class="step-head-container"><div class="step-indicator">3</div><span class="step-label">Kontaktdaten</span></div>
          </div>
        `;
        form.prepend(stepProgress);

        const stepButtons = document.createElement('div');
        stepButtons.className = 'step-buttons';
        stepButtons.innerHTML =` 
          <button type="button" id="backBtn" style="display: none;">Zurück</button>
          <button type="button" id="nextBtn">Anforderungen angeben</button>
        `;

        const hsSubmit = form.querySelector('.hs_submit');
        if (hsSubmit) {
          form.insertBefore(stepButtons, hsSubmit);
        }

        const backBtn = document.getElementById('backBtn');
        const nextBtn = document.getElementById('nextBtn');
        const indicators = document.querySelectorAll('.step-indicator');
        const headContainers = document.querySelectorAll('.step-head-container');

        const totalSteps = 3;
        let currentStep = 0;

        const updateStep = (step) => {
          allFields.forEach(field => {
            const input = field.querySelector('input, select, textarea');
            const name = input?.name;
            field.style.display = stepFields[step].includes(name) ? 'block' : 'none';
          });

          const consentText = form.querySelector('.legal-consent-container');
          if (consentText) {
            consentText.style.display = step === 2 ? 'block' : 'none';
          }

          const hsSubmit = form.querySelector('.hs_submit');
          if (hsSubmit) {
            hsSubmit.style.display = step === 2 ? 'block' : 'none';
          }

          backBtn.style.display = step > 0 ? 'inline-block' : 'none';
          nextBtn.style.display = step === 2 ? 'none' : 'inline-block';
          nextBtn.textContent = step === totalSteps - 2 ? 'Kontaktdaten eingeben' : 'Anforderungen angeben';

          indicators.forEach((el, i) => {
            el.classList.toggle('active', i === step);

            const container = headContainers[i];
            if (i < step) {
              container.classList.add('completed');
            } else {
              container.classList.remove('completed');
            }
          });
        };

        const validateStep = (step) => {
          let valid = true;
          stepFields[step].forEach(name => {
            const field = form.querySelector([name="${name}"]);
            if (field) {
              const wrapper = field.closest('.hs-form-field');
              const errorBox = wrapper?.querySelector('.hs-error-msgs');
              if (field.hasAttribute('required') && !field.value.trim()) {
                valid = false;
                if (errorBox) errorBox.style.display = 'block';
                field.classList.add('input-error');
              } else {
                if (errorBox) errorBox.style.display = 'none';
                field.classList.remove('input-error');
              }
            }
          });
          return valid;
        };

        updateStep(currentStep);

        nextBtn.addEventListener('click', () => {
          if (currentStep === totalSteps - 1) {
            if (validateStep(currentStep)) form.requestSubmit();
          } else {
            if (validateStep(currentStep)) {
              currentStep++;
              updateStep(currentStep);
            }
          }
        });

        backBtn.addEventListener('click', () => {
          if (currentStep > 0) {
            currentStep--;
            updateStep(currentStep);
          }
        });
      }, 100);
    }
  });
</script>

kontakt/?Draeeegrrheryr:666 Uncaught SyntaxError: Failed to execute 'querySelector' on 'Element': '${name}' is not a valid selector.

Assistant
The error is due to incorrect usage of a dynamic selector inside `querySelector`:

const field = form.querySelector([name="${name}"]);

This line is **invalid JavaScript syntax** because `querySelector` expects a string as a parameter, and you're trying to use a template string inside square brackets, which doesn't work.

### ✅ Fix:
Replace the line with proper string interpolation **and quotes** around the `name` attribute:

const field = form.querySelector(`[name="${name}"]`);

### Full fix inside `validateStep`:
Here’s the corrected block:

const validateStep = (step) => {
  let valid = true;
  stepFields[step].forEach(name => {
    const field = form.querySelector(`[name="${name}"]`);
    if (field) {
      const wrapper = field.closest('.hs-form-field');
      const errorBox = wrapper?.querySelector('.hs-error-msgs');
      if (field.hasAttribute('required') && !field.value.trim()) {
        valid = false;
        if (errorBox) errorBox.style.display = 'block';
        field.classList.add('input-error');
      } else {
        if (errorBox) errorBox.style.display = 'none';
        field.classList.remove('input-error');
      }
    }
  });
  return valid;
};

Let me know if you also want to show a toast, scroll to the invalid field, or add animation on validation fail.

User
give the full code
Assistant
Here's the **full, corrected code** including the fixed `querySelector` syntax in the `validateStep` function and everything else intact:

<div id="hubspot-form"></div>

<style>
/* [your existing CSS unchanged] */
... (same CSS from your post)
</style>

<script src="https://js.hsforms.net/forms/v2.js" charset="utf-8"></script>
<script>
  hbspt.forms.create({
    portalId: "6868748",
    formId: "376e8c84-cbc6-408f-8899-55c2af1436ee",
    target: "#hubspot-form",
    onFormReady: function () {
      const waitForFields = setInterval(() => {
        const form = document.querySelector('#hubspot-form form');
        const allFields = form?.querySelectorAll('.hs-form-field');
        if (!form || !allFields || allFields.length < 5) return;

        clearInterval(waitForFields);

        const stepFields = {
          0: ['welche_produkte_wollen_sie_live_sehen_'],
          1: ['message'],
          2: []
        };

        allFields.forEach(field => {
          const input = field.querySelector('input, select, textarea');
          if (input && input.name && !Object.values(stepFields).flat().includes(input.name)) {
            stepFields[2].push(input.name);
          }
        });

        const stepProgress = document.createElement('div');
        stepProgress.innerHTML = `
          <div id="step-progress">
            <div class="step-head-container"><div class="step-indicator active">1</div><span class="step-label">Produktauswahl</span></div>
            <div class="step-head-container"><div class="step-indicator">2</div><span class="step-label">Anforderungen</span></div>
            <div class="step-head-container"><div class="step-indicator">3</div><span class="step-label">Kontaktdaten</span></div>
          </div>
        `;
        form.prepend(stepProgress);

        const stepButtons = document.createElement('div');
        stepButtons.className = 'step-buttons';
        stepButtons.innerHTML =` 
          <button type="button" id="backBtn" style="display: none;">Zurück</button>
          <button type="button" id="nextBtn">Anforderungen angeben</button>
        `;

        const hsSubmit = form.querySelector('.hs_submit');
        if (hsSubmit) {
          form.insertBefore(stepButtons, hsSubmit);
        }

        const backBtn = document.getElementById('backBtn');
        const nextBtn = document.getElementById('nextBtn');
        const indicators = document.querySelectorAll('.step-indicator');
        const headContainers = document.querySelectorAll('.step-head-container');

        const totalSteps = 3;
        let currentStep = 0;

        const updateStep = (step) => {
          allFields.forEach(field => {
            const input = field.querySelector('input, select, textarea');
            const name = input?.name;
            field.style.display = stepFields[step].includes(name) ? 'block' : 'none';
          });

          const consentText = form.querySelector('.legal-consent-container');
          if (consentText) {
            consentText.style.display = step === 2 ? 'block' : 'none';
          }

          const hsSubmit = form.querySelector('.hs_submit');
          if (hsSubmit) {
            hsSubmit.style.display = step === 2 ? 'block' : 'none';
          }

          backBtn.style.display = step > 0 ? 'inline-block' : 'none';
          nextBtn.style.display = step === 2 ? 'none' : 'inline-block';
          nextBtn.textContent = step === totalSteps - 2 ? 'Kontaktdaten eingeben' : 'Anforderungen angeben';

          indicators.forEach((el, i) => {
            el.classList.toggle('active', i === step);

            const container = headContainers[i];
            if (i < step) {
              container.classList.add('completed');
            } else {
              container.classList.remove('completed');
            }
          });
        };

        const validateStep = (step) => {
          let valid = true;
          stepFields[step].forEach(name => {
            const field = form.querySelector(`[name="${name}"]`);
            if (field) {
              const wrapper = field.closest('.hs-form-field');
              const errorBox = wrapper?.querySelector('.hs-error-msgs');
              if (field.hasAttribute('required') && !field.value.trim()) {
                valid = false;
                if (errorBox) errorBox.style.display = 'block';
                field.classList.add('input-error');
              } else {
                if (errorBox) errorBox.style.display = 'none';
                field.classList.remove('input-error');
              }
            }
          });
          return valid;
        };

        updateStep(currentStep);

        nextBtn.addEventListener('click', () => {
          if (currentStep === totalSteps - 1) {
            if (validateStep(currentStep)) form.requestSubmit();
          } else {
            if (validateStep(currentStep)) {
              currentStep++;
              updateStep(currentStep);
            }
          }
        });

        backBtn.addEventListener('click', () => {
          if (currentStep > 0) {
            currentStep--;
            updateStep(currentStep);
          }
        });
      }, 100);
    }
  });
</script>

Let me know if you want enhancements like:
– Auto-scroll to the first invalid field,
– Fade-in/fade-out transition per step,
– Progress bar instead of circles.

Leave a Comment

Your email address will not be published. Required fields are marked *