От автора: в этом руководстве мы узнаем о создании компонента фильтра данных на чистом CSS, для которого не требуется JavaScript. Мы будем использовать простую разметку, некоторые элементы управления формой и некоторые действительно интересные селекторы CSS, которые вы, возможно, раньше не использовали.
Над чем мы работаем
У каждого автора здесь на Tuts + есть собственная страница архива. Мы собираемся воссоздать такой список руководств, используя собственную разметку. Затем мы реализуем компонент, который будет фильтровать записи на основе категорий, к которым они принадлежат. Вот наш окончательный проект:
Давайте построим его!
1. Начинаем с HTML-разметки
Мы начнем с определения категорий фильтров в нашем компоненте. В этом примере мы будем использовать семь фильтров:
All
CSS
JavaScript
jQuery
WordPress
Slider
fullPage.js
Для этого мы сначала определяем семь переключателей, которые группируем через ключевое словом categories. По умолчанию выбрана первая кнопка-переключатель:
<input type="radio" id="All" name="categories" value="All" checked> <input type="radio" id="CSS" name="categories" value="CSS"> <input type="radio" id="JavaScript" name="categories" value="JavaScript"> <input type="radio" id="jQuery" name="categories" value="jQuery"> <input type="radio" id="WordPress" name="categories" value="WordPress"> <input type="radio" id="Slider" name="categories" value="Slider"> <input type="radio" id="fullPage.js" name="categories" value="fullPage.js">
Затем мы создаем упорядоченный список, который содержит метки, связанные с этими переключателями. Помните, что мы связываем переключатель с меткой, устанавливая его значение id равным значению for метки:
<ol class="filters"> <li> <label for="All">All</label> </li> <li> <label for="CSS">CSS</label> </li> <li> <label for="JavaScript">JavaScript</label> </li> <li> <label for="jQuery">jQuery</label> </li> <li> <label for="WordPress">WordPress</label> </li> <li> <label for="Slider">Slider</label> </li> <li> <label for="fullPage.js">fullPage.js</label> </li> </ol>
Затем мы настраиваем другой упорядоченный список, включающий элементы, которые мы хотим фильтровать (наши карточки). Каждый из отфильтрованных элементов будет иметь собственный атрибут data-category, значение которого представляет собой список фильтров, разделенных пробелами:
<ol class="posts"> <li class="post" data-category="CSS JavaScript">...</li> <li class="post" data-category="CSS JavaScript">...</li> <!-- 10 more list items here --> </ol>
В нашем случае фильтруемые элементы будут постами. Таким образом, разметка, которую мы будем использовать для описания поста вместе с его мета-данными (заголовок, изображение, категории), выглядит следующим образом:
<article> <figure> <a href="" target="_blank"> <img src="IMG_SRC" alt=""> </a> <figcaption> <ol class="post-categories"> <li> <a href="">...</a> <li> <!-- possibly more list items here --> </ol> <h2 class="post-title"> <a href="" target="_blank">...</a> </h2> </figcaption> </figure> </article>
Когда разметка готова, давайте обратим внимание на необходимые стили.
2. Определение стилей
Сначала мы визуально скрываем переключатели:
input[type="radio"] { position: absolute; left: -9999px; }
Затем мы добавляем несколько стилей для фильтров:
:root { --black: #1a1a1a; --white: #fff; --green: #49b293; } .filters { text-align: center; margin-bottom: 2rem; } .filters * { display: inline-block; } .filters label { padding: 0.5rem 1rem; margin-bottom: 0.25rem; border-radius: 2rem; min-width: 50px; line-height: normal; cursor: pointer; transition: all 0.1s; } .filters label:hover { background: var(--green); color: var(--white); }
CSS Grid Layout
Далее мы укажем некоторые стили для фильтруемых элементов. Самое главное, мы используем CSS Grid, чтобы уложить их по-разному в зависимости от размера экрана:
:root { --black: #1a1a1a; --white: #fff; --green: #49b293; } .posts { display: grid; grid-gap: 1.5rem; grid-template-columns: repeat(4, 1fr); } .posts .post { background: #fafafa; border: 1px solid rgba(0, 0, 0, 0.1); } .posts .post-title { font-size: 1.3rem; } .posts .post-title:hover { text-decoration: underline; } .posts figcaption { padding: 1rem; } .posts .post-categories { margin-bottom: 0.75rem; font-size: .75rem; } .posts .post-categories * { display: inline-block; } .posts .post-categories li { margin-bottom: 0.2rem; } .posts .post-categories a { padding: 0.2rem 0.5rem; border-radius: 1rem; border: 1px solid; line-height: normal; background: all 0.1s; } .posts .post-categories a:hover { background: var(--green); color: var(--white); } @media screen and (max-width: 900px) { .posts { grid-template-columns: repeat(3, 1fr); } } @media screen and (max-width: 650px) { .posts { grid-template-columns: repeat(2, 1fr); } }
Примечание. Для удобства чтения мы не группируем в CSS общие правила.
Добавление стилей фильтрации
Идея здесь удивительно проста. Каждый раз, когда мы нажимаем на фильтр, должны отображаться только соответствующие отфильтрованные элементы (посты). Для реализации этого функционала мы будем использовать комбинацию следующих вещей:
Псевдо-класс :checked
Обратный псевдо-класс ( :not())
Селекторы атрибутов
Общий комбинатор элементов одного уровня ( ~) переименованный в CSS4 в «последовательно-одноуровневый селектор»
Когда мы нажимаем на фильтр «All», отображаются все посты, имеющие атрибут data-category:
[value="All"]:checked ~ .posts [data-category] { display: block; }
Когда мы нажимаем на любую другую категорию фильтра, будут видны только целевые посты:
[value="CSS"]:checked ~ .posts .post:not([data-category~="CSS"]), [value="JavaScript"]:checked ~ .posts .post:not([data-category~="JavaScript"]), [value="jQuery"]:checked ~ .posts .post:not([data-category~="jQuery"]), [value="WordPress"]:checked ~ .posts .post:not([data-category~="WordPress"]), [value="Slider"]:checked ~ .posts .post:not([data-category~="Slider"]), [value="fullPage.js"]:checked ~ .posts .post:not([data-category~="fullPage.js"]) { display: none; }
Например, когда мы нажимаем на категорию фильтра «Slider «, будут отображаться только посты, принадлежащие этой категории.
Компонент фильтра на чистом CSS в действии
Стоит отметить, что в приведенных выше стилях вместо синтаксиса [att~=val] мы могли бы в равной степени использовать синтаксис [att*=val]. Вот как будет выглядеть это изменение:
[value="CSS"]:checked ~ .posts .post:not([data-category*="CSS"]), [value="JavaScript"]:checked ~ .posts .post:not([data-category*="JavaScript"]), [value="jQuery"]:checked ~ .posts .post:not([data-category*="jQuery"]), [value="WordPress"]:checked ~ .posts .post:not([data-category*="WordPress"]), [value="Slider"]:checked ~ .posts .post:not([data-category*="Slider"]), [value="fullPage.js"]:checked ~ .posts .post:not([data-category*="fullPage.js"]) { display: none; }
Быстрое пояснение CSS-селектора
Что именно указывает этот селектор? Первая часть [value=»CSS»]:checked ищет выбранные переключатели с определенным значением (в данном случае «CSS»).
После этого тильда (~) — это то, что мы сейчас называем «последовательно-одноуровневым селектором». Он выбирает элементы, у которых тот же родительский элемент, что и у предыдущего элемента, даже если они в разметке расположены не рядом. Так что ~ .posts .post ищет элементы, .posts .post, у которых тот же родительский элемент, что и у выбранного переключателя.
Чтобы еще повысить специфичность, мы уточняем наш селектор :not([data-category~=»CSS»]), чтобы он выбирал только те элементы .post, у которых атрибут data-category не содержит значение «CSS» где-то внутри разделенного пробелами списка.
Затем он применяет display: none; к любым элементам, которые соответствуют этим критериям. Это довольно сложный селектор, хотя он вполне логичен. Человеческим языком вы можете описать это как: «Когда выбран переключатель со значением«CSS», найти все элементы, которые не содержат «CSS» в списке категорий данных, и скрыть их».
Завершающие стили
В качестве последнего шага мы добавим правило, которое выделяет активную категорию фильтра:
:root { --black: #1a1a1a; --white: #fff; --green: #49b293; } [value="All"]:checked ~ .filters [for="All"], [value="CSS"]:checked ~ .filters [for="CSS"], [value="JavaScript"]:checked ~ .filters [for="JavaScript"], [value="jQuery"]:checked ~ .filters [for="jQuery"], [value="WordPress"]:checked ~ .filters [for="WordPress"], [value="Slider"]:checked ~ .filters [for="Slider"], [value="fullPage.js"]:checked ~ .filters [for="fullPage.js"] { background: var(--green); color: var(--white); }
3. Доступность
Эта фильтрация доступна по умолчанию; благодаря тому, как работают радио-кнопки и метки, мы можем фильтровать элементы с помощью клавиатуры. Сначала нажмите клавишу Tab, чтобы переместить фокус на выбранный переключатель. Затем нажмите клавиши со стрелками, чтобы переместить фокус и выбрать другие переключатели. Попробуйте сами:
Тем не менее, на самом деле мы отдельно не уделили доступности внимания, поэтому вполне могут иметь место и другие аспекты, которые нуждаются в улучшении.
Заключение
Вот и все! С помощью нескольких правил CSS и структурированной разметки нам удалось создать полностью функциональный компонент фильтра. Надеюсь, вам понравилось это упражнение, и оно помогло вам расширить понимание CSS-селекторов. Как всегда, спасибо за чтение!
Автор: George Martsoukos
Источник: https://webdesign.tutsplus.com
Редакция: Команда webformyself.