Можно ли узнать, пуст ли вход только с помощью CSS?

У меня возник этот вопрос, когда я попытался создать компонент автозаполнения для Learn JavaScript. В принципе, я хотел:

  1. Скрыть раскрывающийся список, если поле ввода пусто
  2. Показать раскрывающийся список, если ввод заполнен

Я нашел способ это сделать. Это не идеально. Здесь есть несколько нюансов, но я хочу поделиться им с вами.

Форма

Во-первых, давайте создадим форму, чтобы мы были на одной странице. Мы собираемся использовать простую форму с одним входом.

<form>
  <label for="input"> Input </label>
  <input type="text" id="input" />
</form>

Когда ввод заполнен, мы хотим изменить его border-color на зеленый. Вот пример того, что мы создаем:

Проверка, пуст ли вход

Я полагался на проверку формы HTML, чтобы проверить, был ли ввод пустым. Это означало, что мне нужен атрибут required.

<form>
  <label> Input </label>
  <input type="text" name="input" id="input" required />
</form>

На этом этапе все работало нормально, когда ввод был заполнен. Границы стали зелеными.

Но возникла проблема: если пользователь вводит пробел в поле, границы тоже становятся зелеными.

Технически это правильно. Вход заполнен, потому что пользователь что-то ввел в него.

Но я не хотел, чтобы пробелы вызывали пустое раскрывающееся меню (для компонента автозаполнения).

Этого было недостаточно. Мне нужна была более строгая проверка.

Дальнейшие проверки

HTML дает вам возможность проверять входные данные с помощью регулярных выражений с атрибутом pattern. Я решил проверить это.

Поскольку я не хотел распознавать пробелы, я начал с шаблона \S+. Этот шаблон означал: один или несколько символов без пробелов.

<form>
  <label> Input </label>
  <input type="text" name="input" id="input" required pattern="\S+"/>
</form>

Конечно, это сработало. Если пользователь вводит пробел в поле, ввод не проверяется.

Но когда во ввод вводится пробел (где угодно), ввод становится недействительным.

К сожалению, в моем варианте использования этот шаблон не сработал.

В компоненте автозаполнения Learn JavaScript я научил студентов, как заполнять список стран. В названиях некоторых стран были пробелы…

Мне пришлось включить в микс пробелы.

Следующая лучшая альтернатива, о которой я мог подумать, - это \S+.*. Это означает 1 или несколько непробельных символов, за которыми следует ноль или более (любых) символов.

<form>
  <label> Input </label>
  <input type="text" name="input" id="input" required pattern="\S+.*"/>
</form>

Это сработало! Теперь я могу вводить пробелы в микс!

Но есть еще одна проблема ... ввод не проверяется, если вы НАЧИНАЕТесь с пробела ...

И это проблема, которую я не мог решить. Подробнее об этом позже.

Когда я работал над этой статьей, я натолкнулся на еще один интересный вопрос: можно ли стилизовать недопустимое состояние, когда ввод заполнен неправильно?

Признание ввода недействительным

Мы не хотим использовать :invalid, потому что мы запускаем ввод с недопустимым состоянием. (Когда ввод пуст, он уже недействителен).

Именно здесь на помощь пришел Крис Койер с « UX проверки форм в HTML и CSS ».

В статье Крис говорит о псевдоклассе :placeholder-shown. Его можно использовать, чтобы проверить, отображается ли заполнитель.

Идея такая:

  1. Вы добавляете заполнитель к своему вводу
  2. Если ввод скрыт, это означает, что пользователь что-то ввел в поле
  3. Продолжить проверку (или признание недействительности)

Вот CSS (упрощенная версия. Полную версию можно найти в статье Криса).

/* Show red borders when filled, but invalid */
input:not(:placeholder-shown) {
  border-color: hsl(0, 76%, 50%);
}

Поскольку у меня были как стили проверки, так и стили недействительности, я должен был убедиться, что действительные стили идут после недопустимых.

/* Show red borders when filled, but invalid */
input:not(:placeholder-shown) {
  border-color: hsl(0, 76%, 50%);;
}
/* Show green borders when valid */
input:valid {
  border-color: hsl(120, 76%, 50%);
}

Вот демонстрация, с которой вы можете поиграть:

См. Ручку Чистая проверка пустого CSS от Зелла Лью (@zellwk) на CodePen.

Примечание. Edge не поддерживает :placeholder-shown, поэтому, вероятно, пока не рекомендуется использовать его в производственной среде. Нет хорошего способа обнаружить эту функцию.

А теперь вернемся к проблеме, которую я не мог решить.

Проблема с узором

Атрибут pattern замечательный, потому что он позволяет вам принимать регулярное выражение. Это регулярное выражение позволяет вам проверять ввод с помощью всего, что вы можете придумать.

Но… регулярное выражение должно полностью соответствовать тексту. Если текст не соответствует полностью, ввод становится недействительным.

Это создало проблему, о которой я упоминал выше. (Напоминание о проблеме: если пользователь сначала вводит пробел, ввод становится недействительным).

Я не мог найти регулярное выражение, которое подходило бы для всех вариантов использования, о которых я думал. Если вы хотите попробовать свои силы в создании нужного мне регулярного выражения, я буду более чем счастлив получить помощь!

Вот варианты использования:

// Should not match
''
' '
'  '
'   '
// Should match
'one-word'
'one-word '
' one-word'
' one-word '
'one phrase with whitespace'
'one phrase with whitespace '
' one phrase with whitespace'
' one phrase with whitespace '

(С другой стороны, я мог бы слишком много об этом подумать… 🙄).

Обновление: проблема решена!

Многие читатели были достаточно великодушны, чтобы прислать мне свои решения по электронной почте. Хочу поблагодарить всех, кто помогал. Большое спасибо!

Самое чистое решение, которое я получил: .*\S.* от Daniel O’Connor. Это означает:

  • .*: любой символ
  • \S: следует один непробельный символ.
  • .*: за ним следует любой символ

Другие регулярные выражения, которые я получил, включают:

И многие другие!

Вот код с обновленным решением Даниэля.

Подведение итогов

Да, можно проверить форму с помощью чистого CSS. Существуют потенциальные проблемы с проверкой, когда используются пробельные символы.

Если вы не возражаете против пробелов, он работает отлично. Удачи, пробуя этот паттерн! (Извините, ничего не могу поделать).

Спасибо за прочтение. Эта статья вам помогла? Если это так, я надеюсь, вы подумаете о том, чтобы поделиться им. Вы могли бы помочь кому-то другому. Огромное спасибо!

Эта статья изначально была размещена в моем блоге. Подпишитесь на мою информационную рассылку, если хотите, чтобы больше статей помогли вам стать лучшим фронтенд-разработчиком.