Соседние селекторы
Соседними называются элементы веб-страницы, когда они следуют непосредственно друг за другом в коде документа.
Синтаксис
Для управления стилем соседних элементов используется символ плюса (+), который устанавливается между двумя селекторами E и F. Пробелы вокруг плюса не обязательны. Стиль при такой записи применяется к элементу F, но только в том случае, если он является соседним для элемента E и следует сразу после него. Рассмотрим несколько примеров.
Lorem ipsum dolor sit amet.
Тег является дочерним по отношению к тегу
, поскольку он находится внутри этого контейнера. Соответственно
выступает в качестве родителя .
Lorem ipsum dolor sit amet.
Теги и никак не перекрываются и представляют собой соседние элементы. То, что они расположены внутри контейнера
, не влияет на их отношение.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Соседними здесь являются теги и , а также и . При этом и к соседним элементам не относятся из-за того, что между ними расположен контейнер .
HTML5 CSS 2.1 IE Cr Op Sa Fx
Соседние селекторы Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Результат данного примера показан на рис. 1.
Рис. 1. Красный цвет текста для соседних селекторов
Браузеры
Браузер Internet Explorer 7 не применяет стиль, если между селекторами располагается комментарий ( B + /* плюс */ I ).
CSS по теме
- [атрибут$=»значение»]
- [атрибут*=»значение»]
- [атрибут=»значение»]
- [атрибут^=»значение»]
- [атрибут|=»значение»]
- [атрибут~=»значение»]
- Вложенные селекторы
- Дочерние селекторы
- Идентификаторы
- Классы
CSS-селекторы
Селектор определяет, к какому элементу применять то или иное CSS-правило.
Обратите внимание — не существует селекторов, которые бы позволили выбрать родителя (содержащий контейнер) или соседа родителя или потомков соседа родителя.
Базовые селекторы
Выбирает все элементы. По желанию, он может быть ограничен определённым пространством имён или относиться ко всему пространству имён.
Синтаксис: * ns|* *|*
Пример: * будет соответствовать всем элементам на странице.
Этот базовый селектор выбирает тип элементов, к которым будет применяться правило.
Синтаксис: элемент
Пример: селектор input выберет все элементы .
Этот базовый селектор выбирает элементы, основываясь на значении их атрибута class .
Синтаксис: .имяКласса
Пример: селектор .index выберет все элементы с соответствующим классом (который был определён в атрибуте class=»index» ).
Этот базовый селектор выбирает элементы, основываясь на значении их id атрибута. Не забывайте, что идентификатор должен быть уникальным, т. е. использоваться только для одного элемента в HTML-документе.
Синтаксис: #имяИдентификатора
Пример: селектор #toc выберет элемент с идентификатором toc (который был определён в атрибуте id=»toc» ).
Этот селектор выбирает все элементы, имеющие данный атрибут или атрибут с определённым значением.
Синтаксис: [attr] [attr=value] [attr~=value] [attr|=value] [attr^=value] [attr$=value] [attr*=value]
Пример: селектор [autoplay] выберет все элементы, у которых есть атрибут autoplay (независимо от его значения).
Ещё пример: a[href$=».jpg»] выберет все ссылки, у которых адрес заканчивается на «.jpg».
Ещё пример: a[href^=»https»] выберет все ссылки, у которых адрес начинается на «https».
Комбинаторы
Комбинатор , это способ группировки, он выбирает все совпадающие узлы.
Синтаксис: A, B
Пример: div, span выберет оба элемента — и и .
Комбинатор ‘ ‘ (пробел) выбирает элементы, которые находятся внутри указанного элемента (вне зависимости от уровня вложенности).
Синтаксис: A B
Пример: селектор div span выберет все элементы , которые находятся внутри элемента .
Комбинатор ‘>’ в отличие от пробела выбирает только те элементы, которые являются дочерними непосредственно по отношению к указанному элементу.
Синтаксис: A > B
Комбинатор ‘~’ выбирает элементы, которые находятся на этом же уровне вложенности, после указанного элемента, с тем же родителем.
Синтаксис: A ~ B
Комбинатор ‘+’ выбирает элемент, который находится непосредственно после указанного элемента, если у них общий родитель.
Синтаксис: A + B
Пример: селектор h2 + p выберет первый элемент , который находится непосредственно после элемента (en-US).
Псевдо
Знак : позволяет выбрать элементы, основываясь на информации, которой нет в дереве элементов.
Пример: a:visited соответствует всем элементам которые имеют статус «посещённые».
Ещё пример: div:hover соответствует элементу, над которым проходит указатель мыши.
Ещё пример: input:focus соответствует полю ввода, которое получило фокус.
Знак :: позволяет выбрать вещи, которых нет в HTML.
Пример: p::first-line соответствует первой линии абзаца .
Версии CSS
Specification |
---|
Selectors Level 4 |
Селекторы — Основы верстки контента
В прошлых уроках и упражнениях мы использовали достаточно простые селекторы. Они позволяли выбрать элементы, к которым будут применены CSS правила. Вы уже умеете выбирать элемент по его тегу, классу, идентификатору и найти вложенный элемент.
CSS дает намного большие возможности по выбору элементов. В этом уроке мы изучим самые популярные селекторы второго и третьего уровня спецификации W3C. В конце урока будут оставлены ссылки на спецификации, в которых вы сможете узнать и о других селекторах.
Выбор соседнего элемента
Ранее использование селекторов указывало, какой конкретно элемент мы хотим выбрать и где он находится относительно своих родительских блоков. В большинстве случаев этого достаточно для точного указания элемента, но бывают случаи, когда нужно выбрать соседний элемент, а не вложенный. Например,
class="time">. class="timer">.
По условию нашей задачи элемент timer полностью зависит от блока time . Предположим, что стиль таймера меняется в зависимости от наличия элемента с классом time . Есть несколько путей решения такой задачи:
- Положить оба элемента в единого родителя и дать им уникальные классы для разных ситуаций.
- Воспользоваться селектором соседнего элемента.
Чаще всего, именно первый вариант будет предпочтительным. При этом вы не раз столкнетесь с ситуациями, когда это невозможно. Такое может происходить при динамическом добавлении элементов на страницу. И тут на помощь приходят селекторы.
В CSS существует два селектора для выбора элемента, который лежит рядом с другим элементом:
- A + B — выбор элемента B, который находится непосредственно после элемента A. Такой селектор называется смежным или соседним
- A ~ B — выбор элемента B, который находится на том же уровне вложенности, что и A. При этом они имеют общего родителя и все элементы B находятся после элемента A в HTML. Такой селектор называется родственным.
Для примера выше отлично подойдет смежный селектор. Элементы time и timer идут друг за другом и являются дочерними элементами одного и того же родителя. Стилизуем элемент timer в зависимости от существования элемента time :
Родственный селектор позволяет немного усложнить ситуацию. Ведь теперь будет возможность не просто выбрать соседний элемент, а элемент, лежащий на том же уровне. Изменим пример, который позволит наглядно продемонстрировать возможность родственного селектора.
. class="time">. . class="timer">.
Схематически CSS будет выглядеть следующим образом:
.time ~ .timer /* Стили элемента */ >
Селекторы по атрибуту
Атрибуты — неизменная часть работы верстальщика и фронтенд-разработчика. Они не всегда несут в себе семантический смысл как, например, атрибуты alt , title , class , id и так далее.
HTML позволяет добавлять любые пользовательские атрибуты и работать с ними. Пользовательскими считаются такие атрибуты, которые мы определяем сами. Их не существует в документациях, спецификациях. Они нужны для разработчиков, чтобы удобнее обращаться к элементам или отделять похожие элементы. Целей может быть много и, с приобретением опыта, особенно при работе с языком JavaScript, вы заметите, что пользовательские атрибуты используются не так редко, как может показаться с самого начала.
Для стилизации таких элементов в CSS существуют специальные селекторы.
Самый простой селектор по атрибуту просто выбирает элемент по его атрибуту. В CSS атрибут записывается внутри квадратных скобок, это и будет самым простым селектором по атрибуту. Для демонстрации создадим свой атрибут data-full-screen — это будет пользовательский атрибут и вы его не найдете в документациях. Для тренировки можете его назвать совершенно другим образом — смысл действий от этого не изменится:
data-full-screen>
section[data-full-screen] width: 100vw; height: 100vh; background: #2196f3; >
Можно выбирать не только по названию атрибута, но и по его значению. В этом случае рядом с именем атрибута указывается его значение в следующем синтаксисе:
data-full-screen="true">
section[data-full-screen="true"] width: 100vw; height: 100vh; background: #2196f3; >
С опытом вы заметите, что многие JavaScript-библиотеки работают именно с пользовательскими атрибутами. Это позволяет добиться изолированности компонентов и их удобного переиспользования.
Бывают ситуации, когда в HTML есть группа элементов с одинаковыми именами атрибутов, но с разными значениями. Причем некоторые из них могут быть похожи друг на друга, составляя части одного компонента. Например,
data-nm-section="catalog"> data-nm-section="catalog-popular"> data-nm-section="catalog-new">
Все три секции, по своей логике, будут иметь похожее оформление. Можно добавить всем одинаковый класс, но существует одна проблема: если элементы добавляются динамически, с помощью JS, то есть вероятность существования такого же класса внутри проекта. Это приведет к коллизии, когда один селектор перебьет свойства другого. Поэтому и используются атрибуты.
Все три секции имеют одинаковую приставку catalog. Это поможет отделить их от остальных названий секций с помощью конструкции [data-nm-section^=»catalog»] . Такой селектор выберет все элементы с атрибутом data-nm-section , значение которого начинается с catalog .
[data-nm-section^="catalog"] width: 50px; height: 50px; margin-bottom: 10px; background: #2196f3; >
Есть еще несколько похожих конструкций, которые ищут «вхождение» подстроки в строку:
- [data-nm-section$=»catalog»] — вхождение подстроки в конце значения атрибута.
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
Делегирование событий
Всплытие и перехват событий позволяет реализовать один из самых важных приёмов разработки – делегирование.
Идея в том, что если у нас есть много элементов, события на которых нужно обрабатывать похожим образом, то вместо того, чтобы назначать обработчик каждому, мы ставим один обработчик на их общего предка.
Из него можно получить целевой элемент event.target , понять на каком именно потомке произошло событие и обработать его.
Рассмотрим пример – диаграмму Ба-Гуа. Это таблица, отражающая древнюю китайскую философию.
Её HTML (схематично):
Квадрат Bagua: Направление, Элемент, Цвет, Значение . Северо-Запад. . . . ещё 2 строки такого же вида. . ещё 2 строки такого же вида.
В этой таблице всего 9 ячеек, но могло бы быть и 99, и даже 9999, не важно.
Он будет использовать event.target , чтобы получить элемент, на котором произошло событие, и подсветить его.
Код будет таким:
let selectedTd; table.onclick = function(event) < let target = event.target; // где был клик? if (target.tagName != 'TD') return; // не на TD? тогда не интересует highlight(target); // подсветить TD >; function highlight(td) < if (selectedTd) < // убрать существующую подсветку, если есть selectedTd.classList.remove('highlight'); >selectedTd = td; selectedTd.classList.add('highlight'); // подсветить новый td >
Однако, у текущей версии кода есть недостаток.
Северо-Запад .
Естественно, если клик произойдёт на элементе , то он станет значением event.target .
Вот улучшенный код:
table.onclick = function(event) < let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) >;
Применение делегирования: действия в разметке
Есть и другие применения делегирования.
Например, нам нужно сделать меню с разными кнопками: «Сохранить (save)», «Загрузить (load)», «Поиск (search)» и т.д. И есть объект с соответствующими методами save , load , search … Как их состыковать?
Первое, что может прийти в голову – это найти каждую кнопку и назначить ей свой обработчик среди методов объекта. Но существует более элегантное решение. Мы можем добавить один обработчик для всего меню и атрибуты data-action для каждой кнопки в соответствии с методами, которые они вызывают:
Обработчик считывает содержимое атрибута и выполняет метод. Взгляните на рабочий пример:
Сохранить
Обратите внимание, что метод this.onClick в строке, отмеченной звёздочкой (*) , привязывается к контексту текущего объекта this . Это важно, т.к. иначе this внутри него будет ссылаться на DOM-элемент ( elem ), а не на объект Menu , и this[action] будет не тем, что нам нужно.
Так что же даёт нам здесь делегирование?
- Не нужно писать код, чтобы присвоить обработчик каждой кнопке. Достаточно просто создать один метод и поместить его в разметку.
- Структура HTML становится по-настоящему гибкой. Мы можем добавлять/удалять кнопки в любое время.
Мы также можем использовать классы .action-save , .action-load , но подход с использованием атрибутов data-action является более семантичным. Их можно использовать и для стилизации в правилах CSS.
Приём проектирования «поведение»
Делегирование событий можно использовать для добавления элементам «поведения» (behavior), декларативно задавая хитрые обработчики установкой специальных HTML-атрибутов и классов.
Приём проектирования «поведение» состоит из двух частей:
- Элементу ставится пользовательский атрибут, описывающий его поведение.
- При помощи делегирования ставится обработчик на документ, который ловит все клики (или другие события) и, если элемент имеет нужный атрибут, производит соответствующее действие.
Поведение: «Счётчик»
Например, здесь HTML-атрибут data-counter добавляет кнопкам поведение: «увеличить значение при клике»:
Счётчик: Ещё счётчик:
Если нажать на кнопку – значение увеличится. Конечно, нам важны не счётчики, а общий подход, который здесь продемонстрирован.
Элементов с атрибутом data-counter может быть сколько угодно. Новые могут добавляться в HTML-код в любой момент. При помощи делегирования мы фактически добавили новый «псевдостандартный» атрибут в HTML, который добавляет элементу новую возможность («поведение»).
Всегда используйте метод addEventListener для обработчиков на уровне документа
Когда мы устанавливаем обработчик событий на объект document , мы всегда должны использовать метод addEventListener , а не document.on , т.к. в случае последнего могут возникать конфликты: новые обработчики будут перезаписывать уже существующие.
Для реального проекта совершенно нормально иметь много обработчиков на элементе document , установленных из разных частей кода.
Поведение: «Переключатель» (Toggler)
Ещё один пример поведения. Сделаем так, что при клике на элемент с атрибутом data-toggle-id будет скрываться/показываться элемент с заданным id :
Ваша почта:
Ещё раз подчеркнём, что мы сделали. Теперь для того, чтобы добавить скрытие-раскрытие любому элементу, даже не надо знать JavaScript, можно просто написать атрибут data-toggle-id .
Это бывает очень удобно – не нужно писать JavaScript-код для каждого элемента, который должен так себя вести. Просто используем поведение. Обработчики на уровне документа сделают это возможным для элемента в любом месте страницы.
Мы можем комбинировать несколько вариантов поведения на одном элементе.
Шаблон «поведение» может служить альтернативой для фрагментов JS-кода в вёрстке.
Итого
Делегирование событий – это здорово! Пожалуй, это один из самых полезных приёмов для работы с DOM.
Он часто используется, если есть много элементов, обработка которых очень схожа, но не только для этого.
- Вешаем обработчик на контейнер.
- В обработчике проверяем исходный элемент event.target .
- Если событие произошло внутри нужного нам элемента, то обрабатываем его.
- Упрощает процесс инициализации и экономит память: не нужно вешать много обработчиков.
- Меньше кода: при добавлении и удалении элементов не нужно ставить или снимать обработчики.
- Удобство изменений DOM: можно массово добавлять или удалять элементы путём изменения innerHTML и ему подобных.
Конечно, у делегирования событий есть свои ограничения:
- Во-первых, событие должно всплывать. Некоторые события этого не делают. Также, низкоуровневые обработчики не должны вызывать event.stopPropagation() .
- Во-вторых, делегирование создаёт дополнительную нагрузку на браузер, ведь обработчик запускается, когда событие происходит в любом месте контейнера, не обязательно на элементах, которые нам интересны. Но обычно эта нагрузка настолько пустяковая, что её даже не стоит принимать во внимание.
Задачи
Спрячьте сообщения с помощью делегирования
важность: 5
Дан список сообщений с кнопками для удаления [x] . Заставьте кнопки работать.
В результате должно работать вот так:
P.S. Используйте делегирование событий. Должен быть лишь один обработчик на элементе-контейнере для всего.