<form id="quiz-form" class="form quiz-popup__form _active" novalidate="novalidate">
  <input type="hidden" name="sessid" id="sessid_14" value="8b300fade3b2357400eccb9332f1bc23">
  <div class="quiz-popup__top">
    <h2 class="quiz-popup__new-title new-title">Валидация формы через setCustomValidity на JS</h2>
  </div>
  <div class="quiz-popup__content">
    <div class="quiz-popup__flex">
      <div class="quiz-popup__col">
        <div class="form-item">
          <label for="phone" class="form-input form-input_name">Телефон</label>
          <input id="phone" name="phone" class="form-input form-input_text" type="tel" placeholder="Телефон" required="">
          <span class="form-alert"></span>
        </div>
        <div class="form-item">
          <label for="email" class="form-input form-input_name">Email</label>
          <input id="email" name="email" class="form-input form-input_text" type="email" placeholder="Email" required>
          <span class="form-alert"></span>
        </div>
        <div class="form-item">
          <label for="comment" class="form-input form-input_name">Комментарий</label>
          <input id="comment" name="comment" class="form-input form-input_text" type="text" value="" placeholder="Комментарий" required>
          <span class="form-alert"></span>
        </div>
        <div class="form-item">
          <span class="form-input form-input_name">Файл jpg, png, doc, docx до 1 Мб</span>
          <input id="file" name="file" class="form-input form-input_hide" type="file" accept=".jpg, .png, .doc, .docx" required>
          <label for="file" class="form-file form-input form-input_file form-input_text icon" data-placeholder="Загрузите файл"></label>
          <span class="form-alert"></span>
          <div class="form-file__wrapper">
            <span class="form-file__name"></span>
            <button class="form-file_remove icon">Х</button>
          </div>
        </div>
        <div class="quiz-form__buttons popup-wrapper__buttons">
          <button id="quiz-form-submit" type="submit" class="form-submit btn">Получить результат</button>
        </div>
      </div>

    </div>
  </div>
</form>
body{
  background-color: #091827;
  color: white;
}
button{
  color: inherit;
  background-color: inherit;
  border: 1px solid;
}
.quiz-popup__col {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    gap: 30px;
}
.form {
  width: 600px;
  margin: 0 auto;
}

.form-input, .form-label {
    display: flex;
    align-items: center;
}
.form-input,
.form-input:before,
.form-input:after,
.form-input *,
.form-input *:before,
.form-input *:after,
.form-label,
.form-label:before,
.form-label:after,
.form-label *,
.form-label *:before,
.form-label *:after,
.form-alert,
.form-alert *
{
    transition: all .3s ease;
}
.form-label,
.form-input_text{
    position: relative;
    padding: 20px;
    border: 1px solid #D6D6DD;
    background: transparent;
    color: #fff;
    font-size: 16px;
    font-weight: 400;
    line-height: normal;
    gap: 20px;
}
.form-input:checked + .form-label{
    border: 1px solid rgba(39, 193, 72, 0.50);
}

.form-input {
    position: relative;
}
.form-input.form-input_hide{
    display: none;
}
.form-input.form-input_text{
    width: 100%;
    justify-content: space-between;
}
.form-input.form-input_text:focus{
    border-color: rgba(39, 193, 72, 0.50);
}
.form-input.form-input_name{
    margin-bottom: 16px;
}
.form-input.form-input_checkbox {
}
.form-label.form-label_checkbox:before{
    content: '';
    border-radius: 4px;
}
.form-label.form-label_checkbox:before,
.form-label.form-label_radio .dot{
    background-color: #E8E8E8;
    width: 24px;
    height: 24px;
    flex-shrink: 0;
}
.form-label.form-label_radio .dot {
    border-radius: 100%;
    border: 2px solid #E8E8E8;
    display: flex;
}
.form-label.form-label_radio .dot:before {
    content: '';
    border-radius: 100%;
    width: 12px;
    height: 12px;
    margin: auto;
    transform: scale(0);
    background-color: #27C148;
}
.form-file.form-input_file{
    border: 1px dashed #D6D6D6;
    cursor: pointer;
}
.form-file_remove{
    margin-left: 8px;
    opacity: 0;
    visibility: hidden;
    display: flex;
    background-color: unset;
}
.form-file_remove.icon:before{
    background-color: black;
    width: 16px;
    height: 16px;
    -webkit-mask-image: url("/local/templates/dresscodeV2/components/itb/quiz.form/quiz-popup-2/images/close.svg");
    mask-image: url("/local/templates/dresscodeV2/components/itb/quiz.form/quiz-popup-2/images/close.svg");
}
.form-file.icon:before{
    content: unset;
}
.form-file.form-input_file:before{
    all: unset;
    content: attr(data-placeholder);
}
.form-file.icon:after{
    content: '';
    background-color: #000;
    -webkit-mask-image: url("/local/templates/dresscodeV2/components/itb/quiz.form/quiz-popup-2/images/form-file.svg");
    mask-image: url("/local/templates/dresscodeV2/components/itb/quiz.form/quiz-popup-2/images/form-file.svg");
    transition: background-color .3s ease;
}
.form-file.icon:hover:after{
    background-color: #27c148;
}
.form-input_text::placeholder,
.form-file.form-input_file:before{
    color: #7A7A7A;
    font-weight: 400;
}

.form-input_checkbox:checked + .form-label.form-label_checkbox:before {
    background: url("/local/templates/dresscodeV2/components/itb/quiz.form/quiz-popup-2/images/checkbox.svg") center / 100% no-repeat #27C148;
}
.form-input_radio:checked + .form-label.form-label_radio .dot{
    border-color: #27C148;
    background-color: #fff;
}
.form-input_radio:checked + .form-label.form-label_radio .dot:before {
    transform: scale(1);
}
.form-submit{
    flex-grow: 1 !important;
}
.form-item{
    position: relative;
}
.form-file__name {
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: inherit;
    overflow-x: hidden;
}
.form-alert,
.form-file__wrapper{
    position: absolute;
    bottom: -24px;
    left: 0;
    font-size: 14px;
    display: flex;
    align-items: center;
    width: 100%;
    opacity: 0;
    visibility: hidden;
}
.form-alert,
.form-file__wrapper._error .form-file__name{
    color: #FE6566;
}
.form-file__wrapper._file-added .form-file__name{
    
}

/*._need-valid .form-input_text,*/
/*._need-valid .form-input_text[aria-invalid=true],*/
._need-valid.form-input_text[aria-describedby],
._need-valid.form-input_text:invalid{
    border-color: #FE6566;
    color: #FE6566;
}
/*._need-valid .form-input_text ~ .form-alert,*/
/*._need-valid .form-input_text[aria-invalid=true] ~ .form-alert,*/
._need-valid.form-input_text[aria-describedby] ~ .form-alert,
._need-valid.form-input_text:invalid ~ .form-alert,
._need-valid.form-input#file:invalid ~ .form-alert,
/*.form-file__wrapper._error,*/
.form-file__wrapper._file-added,
.form-file__wrapper._file-added .form-file_remove{
    opacity: 1;
    visibility: visible;
}
const quizForm = document.querySelector("#quiz-form");
// --------------ЗАГРУЖЕННЫЕ ФАЙЛЫ
const fileButton = quizForm.querySelector("input[type=file]");
const fileWrapper = quizForm.querySelector(".form-file__wrapper");
const fileName = quizForm.querySelector(".form-file__name");
const fileRemove = quizForm.querySelector(".form-file_remove");
// --------------ПОЛЯ
const inputs = quizForm.querySelectorAll("input:not([type=hidden])");
// --------------ОШИБКИ
const alerts = quizForm.querySelectorAll("input ~ .form-alert");
inputs.forEach((input, i) => {
  input.oninput = (e) => {
    checkValid(e.target, alerts[i]);
    if (e.target.value == "" && !e.target.required) {
      e.target.classList.remove("_need-valid");
      e.target.setCustomValidity("");
    }
  };
});
// --------------РЕГУЛЯРКА EMAIL
function emailTest(input) {
  return /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,8})$/.test(input.value);
}
// --------------РЕГУЛЯРКА ТЕЛЕФОНА
function telTest(input) {
  return /^(\+7|7|8)[\s(]*\d{3}[)\s]*\d{3}[\s-]?\d{2}[\s-]?\d{2}$/.test(
    input.value
  );
}
function checkValid(input, alert) {
  let name = input.name;
  if (input.value == "" && input.required) {
    input.classList.add("_need-valid");
    if (name == "file") input.setCustomValidity("Выберите файл");
    else input.setCustomValidity("Введите поле");
  } else if (name == "file") {
    input.classList.add("_need-valid");
    input.setCustomValidity(fileTest(input));
  } else if (name == "phone" && !telTest(input)) {
    input.classList.add("_need-valid");
    input.setCustomValidity("Пример номера: 8 123 456 78 90");
  } else if (name == "email" && !emailTest(input)) {
    input.classList.add("_need-valid");
    input.setCustomValidity("Пример email: test@mail.ru");
  } else {
    input.classList.remove("_need-valid");
    input.setCustomValidity("");
  }
  alert.innerHTML = input.validationMessage;
}
function fileTest(input) {
  fileInputClear();
  let file = input.files[0];
  const types = [
    "image/jpeg",
    "image/png",
    "application/msword",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
  ];
  if (!types.includes(file.type)) {
    return "Разрешены файлы в формате .jpg, .png, .doc, .docx";
  }
  if (file.size > 1 * 1024 * 1024) {
    return "Размер файла превышает 1 Мб";
  }
  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onerror = () => {return "Ошибка получения файла"}
  fileName.textContent = fileButton.files[0].name;
  fileWrapper.classList.add("_file-added");
  // -----ПРИ УСПЕХЕ ВЫСТАВИТЬ setCustomValidity('')
  return "";
}

fileRemove.addEventListener("click", (e) => {
  fileButton.value = "";
  fileInputClear(e);
});

function fileInputClear(e = null) {
  if (e != null) e.preventDefault();
  // fileButton.value = '';
  fileName.textContent = "";
  fileWrapper.classList.remove("_file-added");
}
quizForm.addEventListener("submit", function (e) {
  e.preventDefault();
  let form = e.target;
  if (!form.checkValidity()) {
    inputs.forEach((input, i) => {
      if (input.required) {
        checkValid(input, alerts[i]);
      }
    });
  } else {
    alert("valid");
  }
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.