Как найти слово в css

Привет! Меня зовут Иван, я руковожу горизонталью автоматизации тестирования в Skyeng. Часть моей работы — обучать ручных тестировщиков ремеслу автоматизации. И тема с поиском локаторов, по моему опыту, самая тяжкая для изучения. Здесь куча нюансов, которые надо учитывать. Но стоит разобраться, и локаторы начинают бросаться в глаза сами. Хороший автоматизатор должен идеально уметь находить читабельные и краткие локаторы на странице. Об этом и пойдет речь ниже.

Наливаем чай-кофе и погнали!

Что такое локатор

Локатор — обычный текст, которой идентифицирует себя как элемент DOM’а страницы. Простым языком: с помощью локатора на странице можно найти элементы. В случае CSS — локатор включает в себя набор уникальных атрибутов элемента, а в случае XPath — это путь по DOM’у к элементу. 

Если вы изучали CSS ранее, то в конструкции ниже p будет являться локатором элемента, также и атрибут color: red может являться его локатором. Атрибут элемента это всё, что идёт после тега. Например, в теге <p class=”element” id=”value”> атрибутами являются class и id.

p: {
 color: red;
}

Сразу оговорка по терминологии, локатор = селектор.

Локатор — это название селектора на русском. Иногда встречаю в интернете, что селектор относится только к CSS, но это не совсем так. XPath-локатор тоже может быть, просто означает он путь к элементу в DOM’е. Давайте похоливарим в комментах, чем же всё-таки локатор отличается от селектора  ;)

DOM страницы — это HTML-код, написанный человеком или сгенерированный фреймворком, который преобразуется браузером в DOM. То есть набор объектов, где каждый объект — это HTML-тег.

Есть очень много видов локаторов, но чаще всего в работе применяется лишь часть из них. Их можно искать по следующим видам:

  • имя элемента

  • id

  • классы

  • кастомные атрибуты

  • родители и дети элементов

  • ссылки

  • и так далее.

Полное строение элемента

Элемент состоит из имени, то есть самого HTML-тега. Например, div, span, input, button и другие. Внутри него перечислены атрибуты, которые отвечают за все возможные свойства элемента. Например, цвет, размер, действие, которое будет происходить по клику на элемент.

У элемента может быть родитель и ребёнок. Родитель может быть один, а детей может быть несколько. Если детей несколько, то они являются соседями и каждый из них образует свою ось. 1 ребёнок = 1 ось со своими особенностями и своими вложенными элементами. А — родитель, B D E F W X Y — дети A. У каждого элемента есть свои дети, свои дальнейшие ветки, это и называется оси.

Поиск локаторов в браузере

Для поиска элементов в DOM’е страницы нужны средства разработчиков в браузере. Рассмотрим их на примере Chrome. Они же называются DevTools (F12). Нас интересует вкладка Elements, именно там находятся все элементы. Чтобы найти локатор в поле Elements, нужно нажать Ctrl+F. Внизу появится небольшое поле поиска, с ним мы будем работать всё время.

Давайте попробуем найти элемент по названию HTML-тега. Искать просто: в строке поиска вводим название тега. Скорее всего этот локатор элемента будет не уникальным и по его значению найдутся много элементов. Для тестов важно, чтобы был только один элемент для взаимодействия. Если одному локатору будут соответствовать несколько элементов, то тест или будет взаимодействовать с первым из них, или просто упадёт с ошибкой. Элементы можно искать не только с помощью тегов (p, span, div и т.д.), но и с помощью атрибутов тега. Например, color=”red” и class=”button”. Подробнее об этом чуть ниже.

Мы пытаемся найти элемент по тегу button, нам вернулось 269 результатов.

Мы пытаемся найти элемент по тегу button, нам вернулось 269 результатов.

Микро-задание: попробуй открыть DevTools на этой страничке (F12) и найти (Ctrl + F) количество элементов с тегом button. 

P.S. поздравляю, ты уже написал свой первый локатор! Дальше — больше :)

Уникальные локаторы

Где будем практиковаться? https://eu.battle.net/login/ru/ — простая и понятная форма авторизации.

Рассмотрим поиск на примере формы авторизации и регистрации. В коде страницы есть 2 поля («Почта» и «Пароль») и кнопка «Авторизация». Сравним, по каким атрибутам можно найти локатор и определим уникальные атрибуты.

Подробно разберём, как можно найти локатор поля Почта:

Остальные не приложил, потому что значения атрибутов или слишком длинные, или не несут какого-то смысла.

Остальные не приложил, потому что значения атрибутов или слишком длинные, или не несут какого-то смысла.

Разберём, как можно найти локатор поля Пароль:

Больше примеров не добавлял — аналогично с предыдущим: другие значения атрибутов слишком длинные.

Больше примеров не добавлял — аналогично с предыдущим: другие значения атрибутов слишком длинные.

Разберём, как можно найти локатор поля Авторизация:

Начнём с разбора не уникальных локаторов. Если по локатору находятся 2 и более элементов на HTML-странице, такой локатор можно назвать неуникальным. Тест при обнаружении большого количества элементов по данному локатору упадёт или возьмёт первый. Ненадежно, точно не наш бро.

Уникальный, но non-suitable локатор. Если мы в DevTools введем вышеуказанные названия, то найдется элемент. И здесь мы опускаемся до следующего уровня написания локаторов — уровня понятности, читаемости и надёжности локатора.

  • title=»Электронная почта или телефон» — считается плохим паттерном писать локаторы с русским текстом. Тем более в примере текст в title еще и длинный, это визуально громоздко. На текст завязываться можно в крайнем случае, но нужно быть готовым к тому, что тексты часто меняются, любая правка может сломать автотесты.

  • title=»Пароль» — аналогично ^

  • type=»text» — представь, ты открываешь среду разработки и видишь локатор “тип=текст”. Совсем не ясно, к какому элементу относится локатор. Со смысловой точки зрения, это неудачный локатор, потому что он не передаёт смысл локатора.

  • type=»password» — этот атрибут говорит о том, что у поля тип «password» и все символы, которые мы вводим заменяются на звёздочки/точки. При добавлении еще одного поля с type=”password” (например, поле «Подтвердите пароль») локатор сразу станет неактуальным. Стараемся думать наперёд.

Уникальные локаторы. Они найдут только один элемент, они осмысленные, иногда читабельные и краткие. Как раз уникальные атрибуты — это class, id, name и подобные. Они точно наши бро!

Небольшой итог

Хороший локатор — краткий, читабельный и осмысленный. Например, у поля «Пароль» хорошо иметь в локаторе слово password.

Возникает вопрос, почему class=»btn-block btn btn-primary submit-button btn-block» был вынесен в категорию уникальных? Такие локаторы встречаются повсеместно, и именно их мы берём за основу и приводим к красивому виду.

Поиск элементов с помощью CSS

id и class — самые важные атрибуты, с помощью которых мы будем искать бóльшую часть элементов на странице. Есть очень много тонкостей по работе с ними, постараемся рассмотреть все из них. 

Кнопка «Авторизация» имеет несколько классов в одном:

  • btn-block

  • btn

  • btn-primary

  • submit-button

  • btn-block

Каждый из этих классов определяет свой визуал кнопки. Например, btn-primary определяет цвет кнопки, submit-button увеличивает её размер (это лишь догадки, основное значение знают только Blizzard). Несколько классов внутри атрибута class разделяются пробелом.

Наличие более одного класса внутри атрибута говорит о том, что он комбинированный. Бывают и комбинированные атрибуты кроме классов. Но классы необязательно будут уникальны для одного элемента. В данном случае у кнопки «Авторизация» такие атрибуты: 

class="btn-block btn btn-primary submit-button btn-block"

Но если добавить туда кнопку «Регистрация», то может отличаться лишь один класс. Например, он будет выглядеть следующим образом:

class="btn-block btn btn-primary registration-button btn-block"

Сразу заметно, что отличается всего лишь один класс — submit-button сменился на registration-button. Остальные свойства могут иметь и другие кнопки.

Читабельность локатора

Допустим, мы ищем элемент по полному классу. Это хороший и действенный способ. Почти всегда элемент будет уникальным, но очень нечитабельным и громоздким, как в случае с кнопкой «Авторизация».

class с помощью CSS можно записать следующим образом:

  • .locator (точка — сокращенная запись class’а)

  • или выделяем название и значение класса в квадратные скобочки: [class=”value”]

Полный класс элемента кнопки «Авторизация» состоит из 5 классов: btn-block btn btn-primary submit-button btn-block, а выглядеть полный локатор будет так:

[class=”btn-block btn btn-primary submit-button btn-block”]

Разделение происходит с помощью пробела внутри. Для класса его сокращенной формой является точка, поэтому можно записать локатор так:

btn-block.btn.btn-primary.submit-button.btn-block 

Да, стало короче, но всё равно есть смысловая перегрузка. Сокращаем дальше.

Отдельно здесь стоит добавить про поиск по подстроке. Запись [class=”локатор”] ищет только всю строку класса элемента. Если мы напишем [class=”btn-block”] или любой другой класс, то кнопка «Авторизация» не будет найдена. Но если мы запишем локатор полностью [class=”btn-block btn btn-primary submit-button btn-block”], то кнопка найдётся.

Из данной ситуации помогает найти выход символ звёздочки. Он ищет ПОДстроку в строке, то есть часть локатора может найти элемент.

Краткость локатора

Про подстроку

Можно почитать на википедии, там приведён доступный пример для общего понимания поиска по подстроке. Также поиск по подстроке можно сравнить с методом includes из JS

Локатор кнопки«Авторизация» [class=”btn-block btn btn-primary submit-button btn-block”] можно записать следующим образом:

  • [class*=”btn-block”]

  • [class*=”submit-button”]

  • [class*=”btn-block btn”]

  • [class*=”btn btn-primary”]

  • [class*=”primary submit”] (конец одного класса и начала другого, но только в том случае, если они написаны подряд, друг за другом)

  • можно даже сократить название подкласса: не длинное submit-button, а просто submit, например, [class*=”submit”]. Можно даже сократить слово submit — [class*=”sub”].

Важно понимать, это будет работать, если классы идут только последовательно. Если мы укажем [class*=”btn-block submit-button”], то локатор работать не будет, потому что между btn-block и submit-button идут несколько классов: btn и btn-primary. Но это можно обойти, разделив локатор на 2 разных. Например, 2 класса слитно — [class*=”btn-block”][class*=”submit-button”]. Это работает и часто пригождается, когда нужно уточнить, в каком именно элементе мы ищем определенный класс.

Также можно комбинировать краткую запись с помощью точки и тега элемента:

  • .submit-button = [class*=”submit-button”]

  • .btn = [class*=”btn”]

  • .btn-block = [class*=”btn-block”]

  • button[class*=”submit-button”] = button.submit-button

  • button[class*=”btn”] = button.btn

  • button[class*=”btn”][class*=“submit-button”] = button.btn.submit-button

  • button[class*=”submit”]

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

Лаконичность локатора

Мы можем определить кнопку «Авторизация» по классу submit-button. Это не самый лаконичный локатор, но дословно означает действие отправки данных на сервер с формы авторизации. Но что делать, если у кнопки нет контекста? Например, классы кнопки Авторизации будут выглядеть так: [class=”btn-block btn btn-primary btn-block”]. Если нет контекста из слова submit (отправка), то можно очень быстро потеряться и сразу не ясно, к какому элементу относится этот локатор. В данном случае нам поможет название текущего элемента или его родителя.

Для наглядности рассмотрим весь блок с кнопкой «Авторизация».

Как вариант — к локатору можно добавить сам тег button. Например, button[class*=”btn”] (сократил класс для наглядности). В таком случае можно взять тег или класс родителя за основу, а именно div или [class=»control-group submit no-cancel»]. Если нужно указать родителя, то эта связь пишется через пробел. Через пробел можно обращаться на любой уровень вложенности, например, из form сразу прыгнуть к button. Полный путь будет выглядеть так: form div button.

С полученными знаниями можно расширить пул локаторов:  

  • form button

  • form [type=”submit”]

  • #password-form #submit (решётка — сокращённая форма id, точка — сокращённая форма class)

  • и еще много-много локаторов, которые можно найти комбинаторикой, главное, чтобы по итогу локатор выглядел кратко и лаконично, передавал суть элемента

А как с ID

С ID работает всё точно также, только краткая запись ID — это решётка, например, <form id=”password-form”> можно записать как form#password-form, по такому же принципу, как и с классом

Поиск по кастомным атрибутам

Кастомные атрибуты тоже заслуживают упоминания. У элемента могут быть не только классы и айдишники, но и еще бесконечно множество атрибутов. В исключительных случаях можно искать элементы по этим атрибутам, но только в случае их приличного вида. Например, в случае кнопки «Авторизация» указаны несколько необычных атрибутов, которые вряд ли можно использовать за основу для её поиска:

  • data-loading-text

  • tabindex=»0″

Очень хорошей практикой на проекте является обвешивание интерактивных элементов кастомным атрибутом data-qa или data-qa-id. Например, <button id=”css-1232” data-qa=”login-button”>. Если поменяют локатор, то этот атрибут останется и тесты будут стабильными долгое время. Добавлять эти атрибуты могут фронтенд-разработчики или автоматизаторы, если имеют доступ к коду фронтенда и возможность пушить в него правки.

Локаторы можно и нужно комбинировать! Элементы, состоящие из нескольких классов, айди и других атрибутов, можно объединять в один локатор. Например, возьмем элемент формы, который находится выше кнопки «Авторизация»: form#password-form[method=”post”][class*=”username”]

Итоги поиска локаторов с помощью CSS

  • классы и id можно писать сокращенно с помощью точки и решетки

  • <button class=”login”>: .login = [class=”login”] = [class*=”log”] = button.login = button[class=”login”]

  • <button id=”size”>: #size = [id=”size”] = [id*=”ze”] = button#size = button[id=”size”]

  • всё, что не class, и не id в сокращённом виде пишем в [] (квадратных скобках), например, [name=”phone”], [data-qa-id=”regButton”]

  • если тег лежит внутри другого тега, то переходим к нему через пробел (независимо от степени вложенности), например, <span> -> <button> -> <a> = span a = button a = span button a

Поиск элементов с помощью XPath

XPath в корне отличается от CSS как идеей, так и реализацией. XPath — это полноценный язык для поиска элементов в дереве, причём неважно каком, будь это XML или XHTML. Можно использовать XPath в веб-страницах, нативной мобильной вёрстке и других инструментах. 

Я изучал XPath больше месяца с нуля. Проблема была в том, что я никак не понимал принцип его работы — мы ходим от элемента к элементу, но не ясно, как это происходит, как писать красивые пути, какие преимущества у такого подхода. Неделями изучал документацию, статьи на блогах (к сожалению, тогда еще не было человекопонятных статей на Хабре) и видео в ютубе. Мне очень помогло одно видео, где автор объяснял базовые принципы XPath, после чего меня осенило и в голове сложилась картинка. Поэтому хочу поделиться с вами этой информацией, чтобы сократить время на изучение тонны материала. Изучение XPath самостоятельно полезно, но я бы с огромным удовольствием потратил полтора месяца на вещи поважнее.

Предположим, у нас есть следующая структура документа:

<div class="popup">
		<div id="payment-popup">
			<button name="regButton">
				<span href="/doReg">Кнопка</span>
			</button>
		</div>
	</div>

XPath — это путь от элемента к элементу. Можно представить, что структура тегов — это дерево каталогов, как в любой ОС. Например, в данном случае теги можно представить в виде папок: div -> div -> button -> span. В терминале по ним можно переключаться через команду cd, а именно: cd div/div/button/span

div/div/button/span — это и есть путь к элементу с помощью XPath, только первый элемент ищут по всему дереву элементов, поэтому пишут // в начале строки. В данном случае это будет выглядеть так: //div/div/button/span. 2 слэша можно использовать не только в начале — они обозначают то, что мы ищем элемент где-то внутри. Например, //div//span — элемент будет найден, мы пропустили второй div и button

Главная отличительная особенность XPath — возможность проходить не только от родителя к детям, но и от детей к родителям. Например, есть структура:

<div class=”popup”>
	<div id=”payment-popup”>
		<button name=”regButton”>
			<span href=”/doReg” />
		</button>
		<button name=”loginButton”>
			<span href=”/doLogin” />
		</button>
	</div>
</div>

Мы можем перейти от кнопки doLogin в кнопку doReg вот так:

//*[@href=”/doLogin”]/../..//*[@href=”/doReg”]

Чтобы перейти на уровень выше, как и терминале ОС, нужно написать 2 точки, как показано в примере. С помощью 2 точек мы поднимаемся с уровня span сначала до button, а с button до общего div

Главный вопрос, который может возникнуть, а где это может пригодиться? Практически всюду, где есть одинаковые блоки, которые отличаются по какому-то одному признаку. Возьмем страницу RDR2 в Epic Games. На середине страницы сейчас перечислены 3 издания:

В DevTools отчётливо видно, что блоки идентичные. Отличия только в названии издания, описании и цене.

Есть задача: нажмите на кнопку «Купить сейчас» у издания Red Dead Online. Для этого надо завязаться на текст издания, подняться до первого общего элемента у названия издания и кнопки и опуститься до кнопки «Купить сейчас».

//*[contains(text(), “Red Dead Online”)]/ancestor::*[contains(@data-component, "OfferCard")]//*[contains(@data-component, "Purchase")]

Лайфхак: как найти первый общий элемент у двух элементов?

Нажимаем на любом элементе ПКМ -> Посмотреть код, открывается вкладка Elements. Наводим курсором на текущий элемент и он выделяется синим цветом. Просто тащим курсор наверх, пока визуально не найдём элемент, который объединяет 2 элемента — в нашем случае текст и кнопку «Купить сейчас».

В XPath, как и в CSS, можно искать по элементам и по атрибутам в элементе. Например: 

<div class=”popup”>
	<div id=”payment-popup”>
		<button name=”regButton”>
			<span href=”/doReg” />
		</button>
    
    <button name=”loginButton”>
			<span href=”/doLogin” />
		</button>
	</div>
</div>

Можно найти кнопку регистрации: 

  • //*[@href=”/doReg”] или //span[@href=”/doReg”]

  • //*[@name=”regButton”] или //button[@name=”regButton”]

Как мы можем заметить — звёздочка заменяет название элемента. Где стоит звёздочка, означает, что элемент может называться как угодно. Главное, чтобы внутри него был заданный атрибут. Если мы хотим указать конкретный элемент, то подставляем его вместо звёздочки. Например, путь //span[@href=”/doReg”] — сразу говорит нам, что в элементе span мы ищем @href=”/doReg”, но если нам не важен элемент, то тогда span заменяем на звёздочку //*[@href=”/doReg”].

Атрибуты всегда пишутся со знаком @ в начале, это тоже особенность языка.

Еще следует упомянуть переходы по смежным осям. В примере выше есть 2 разные оси — 2 button: элементы одинаковые, но отвечают за разные кнопки. Это можно сделать с помощью зарезервированных слов: following-sibling и preceding-sibling.

Например, нам нужно достать кнопку Войти, зная кнопку Регистрация: //*[@name=”regButton”]/following-sibling::*[@name=”loginButton”]. Если нужно найти кнопку Регистрации зная кнопку Войти, то делается это точно также, только ищем в осях, идущих до кнопки Регистрации: //*[@name=”loginButton”]/preceding-sibling::*[@name=”regButton”]. Переходы между осями или дереву (вверх-вниз) всегда происходит через 2 точки, если мы пишем полное название направления, например, following-sibling::, ancestor::

Не всегда есть возможность искать элементы по полному названию класса, так как оно может являться достаточно большим и нечитабельным. В CSS мы это делали с помощью символа звёздочки. Здесь звёздочку заменяет слово contains и работает точно также, как и в CSS. Например, ищем кнопку Войти: //*[contains(@name, “Login”)]. Как мы видим, contains — это что-то вроде функции в XPath. 1 параметр — атрибут, в котором ищем часть текста, 2 — сам текст.

Последней функцией, которую мы рассмотрим, будет text(). Она позволяет искать элемент по тексту, который в нём находится. Например, есть HTML-разметка:

<button>
	<span>Кнопка Войти</span>
</button>
<button>
	<span>Кнопка Регистрация</span>
</button>

Чтобы найти текст по точному совпадению, нужно писать следующий путь: //*[text()=”Кнопка Войти”]. Но если мы захотим искать по 1 слову, то на помощь приходит комбинация со словом contains, а именно: //*[contains(text(), “Войти”)].

Коротко про «Гибкие локаторы»

Термин «гибкий локатор» применяется к поиску локаторов через CSS и с XPath. Называется он гибким, потому что независимо от текста внутри — локатор не изменится. Для примера снова возьмём страничку с игрой RDR2. На ней есть 3 издания. Сами локаторы не меняются, меняется только текст (название, описание, цена). Общий шаблон локатора будет выглядеть так: //*[contains(text(), “Название издания”)]/ancestor::*[contains(@data-component, «OfferCard»)]//*[contains(@data-component, «Purchase»)]. Текст уже можем в него передавать любой, какой захотим. Так вот именно этот локатор будет называться гибким — его тело остаётся неизменным, а меняются лишь параметры внутри него. В автоматизации мы очень часто пользуемся гибкими локаторами.

Выводы

Мы разобрали 2 основных способа поиска элементов на странице, с помощью CSS и XPath. Небольшое сравнение этих методов:

Плюсы CSS

Минусы CSS

— краткий

— читабельный

— простой для освоения и полностью граничит с изучением базового CSS

— что-то вроде мифа — он работает быстрее, то есть быстрее ищет элемент на странице, но на фоне мощности современных процессоров эта разница во времени неощутима и составляет пару миллисекунд

— может переходить только от родителя к ребёнку, но не наоборот — вверх подниматься нельзя

— более ограниченный набор функций для поиска элементов, например, нельзя искать элемент по тексту, который в нём находится

— CSS заточен только под веб-страницы

Плюсы XPath

Минусы XPath

— полноценный язык для поиска элементов не только в вебе, но и в других средах и документах

— позволяет перемещаться по дереву вниз и вверх

— гибко работает с осями элементов

— есть очень много функций, которые помогают в поиске локаторов, например, поиску по тексту в элементе или аналог normalize-space, который убирает пробелы у строки по бокам

— громоздкий

— нечитабельный

— сложен в освоении

— работает дольше, чем поиск по CSS, хоть и незначительно

В тестах лучше использовать CSS, но это не всегда реально. Именно поэтому в таких случаях приходит на помощь XPath.

Полезные ссылки

CSS:

  • https://flukeout.github.io/ — практика в поиске локаторов.

  • https://code.tutsplus.com/ru/tutorials/the-30-css-selectors-you-must-memorize—net-16048 — полезно узнать про различные виды селекторов. Мы используем не все, но всегда бывает ситуация, когда раз в жизни придётся использовать тот или иной локатор.

  • https://appletree.or.kr/quick_reference_cards/CSS/CSS%20selectors%20cheatsheet.pdf — локаторы наглядно.

  • https://learn.javascript.ru/css-selectors — оформление в виде документации.

XPath:

  • https://topswagcode.com/xpath/ — практика в поиске локаторов.

  • https://www.w3schools.com/xml/xpath_nodes.asp — подробнее про ноды.

  • https://www.w3schools.com/xml/xpath_syntax.asp — синтаксис.

  • https://www.w3schools.com/xml/xpath_axes.asp — оси.

  • https://soltau.ru/index.php/themes/dev/item/413-kratkoe-rukovodstvo-po-xpath — более подробная информация с примерами на русском.

I am looking for a CSS selector for the following table:

Peter    | male    | 34
Susanne  | female  | 12

Is there any selector to match all TDs containing «male»?

BoltClock's user avatar

BoltClock

695k159 gold badges1384 silver badges1352 bronze badges

asked Oct 5, 2009 at 14:26

jantimon's user avatar

8

If I read the specification correctly, no.

You can match on an element, the name of an attribute in the element, and the value of a named attribute in an element. I don’t see anything for matching content within an element, though.

answered Oct 5, 2009 at 14:33

Dean J's user avatar

Dean JDean J

39.1k16 gold badges67 silver badges93 bronze badges

3

Using jQuery:

$('td:contains("male")')

Aliaksei Kliuchnikau's user avatar

answered Jan 31, 2012 at 15:04

moettinger's user avatar

moettingermoettinger

4,8932 gold badges15 silver badges20 bronze badges

8

You’d have to add a data attribute to the rows called data-gender with a male or female value and use the attribute selector:

HTML:

<td data-gender="male">...</td>

CSS:

td[data-gender="male"] { ... }

Rudolph Gottesheim's user avatar

answered Oct 5, 2009 at 14:39

Esteban Küber's user avatar

Esteban KüberEsteban Küber

36.2k15 gold badges79 silver badges97 bronze badges

4

There is actually a very conceptual basis for why this hasn’t been implemented. It is a combination of basically 3 aspects:

  1. The text content of an element is effectively a child of that element
  2. You cannot target the text content directly
  3. CSS does not allow for ascension with selectors

These 3 together mean that by the time you have the text content you cannot ascend back to the containing element, and you cannot style the present text. This is likely significant as descending only allows for a singular tracking of context and SAX style parsing. Ascending or other selectors involving other axes introduce the need for more complex traversal or similar solutions that would greatly complicate the application of CSS to the DOM.

answered Oct 30, 2012 at 20:44

Matt Whipple's user avatar

Matt WhippleMatt Whipple

7,0241 gold badge23 silver badges34 bronze badges

3

You could set content as data attribute and then use attribute selectors, as shown here:

/* Select every cell matching the word "male" */
td[data-content="male"] {
  color: red;
}

/* Select every cell starting on "p" case insensitive */
td[data-content^="p" i] {
  color: blue;
}

/* Select every cell containing "4" */
td[data-content*="4"] {
  color: green;
}
<table>
  <tr>
    <td data-content="Peter">Peter</td>
    <td data-content="male">male</td>
    <td data-content="34">34</td>
  </tr>
  <tr>
    <td data-content="Susanne">Susanne</td>
    <td data-content="female">female</td>
    <td data-content="14">14</td>
  </tr>
</table>

You can also use jQuery to easily set the data-content attributes:

$(function(){
  $("td").each(function(){
    var $this = $(this);
    $this.attr("data-content", $this.text());
  });
});

toms's user avatar

toms

5056 silver badges23 bronze badges

answered Dec 22, 2016 at 10:59

Buksy's user avatar

BuksyBuksy

11.4k8 gold badges62 silver badges68 bronze badges

4

As CSS lacks this feature you will have to use JavaScript to style cells by content. For example with XPath’s contains:

var elms = document.evaluate( "//td[contains(., 'male')]", node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null )

Then use the result like so:

for ( var i=0 ; i < elms.snapshotLength; i++ ){
   elms.snapshotItem(i).style.background = "pink";
}

https://jsfiddle.net/gaby_de_wilde/o7bka7Ls/9/

Gerold Broser's user avatar

answered May 11, 2016 at 8:21

user40521's user avatar

user40521user40521

1,93720 silver badges7 bronze badges

4

I’m afraid this is not possible, because the content is no attribute nor is it accessible via a pseudo class. The full list of CSS3 selectors can be found in the CSS3 specification.

Esteban Küber's user avatar

answered Oct 5, 2009 at 14:33

Edwin V.'s user avatar

Edwin V.Edwin V.

1,3178 silver badges11 bronze badges

0

For those who are looking to do Selenium CSS text selections, this script might be of some use.

The trick is to select the parent of the element that you are looking for, and then search for the child that has the text:

public static IWebElement FindByText(this IWebDriver driver, string text)
{
    var list = driver.FindElement(By.CssSelector("#RiskAddressList"));
    var element = ((IJavaScriptExecutor)driver).ExecuteScript(string.Format(" var x = $(arguments[0]).find(":contains('{0}')"); return x;", text), list);
    return ((System.Collections.ObjectModel.ReadOnlyCollection<IWebElement>)element)[0];
}

This will return the first element if there is more than one since it’s always one element, in my case.

the Tin Man's user avatar

the Tin Man

158k42 gold badges214 silver badges302 bronze badges

answered Jan 20, 2015 at 16:21

Matas Vaitkevicius's user avatar

1

If you don’t create the DOM yourself (e.g. in a userscript) you can do the following with pure JS:

for ( td of document.querySelectorAll('td') ) {
  console.debug("text:", td, td.innerText)
  td.setAttribute('text', td.innerText)
}
for ( td of document.querySelectorAll('td[text="male"]') )
  console.debug("male:", td, td.innerText)
<table>
  <tr>
    <td>Peter</td>
    <td>male</td>
    <td>34</td>
  </tr>
  <tr>
    <td>Susanne</td>
    <td>female</td>
    <td>12</td>
  </tr>
</table>

Console output

text: <td> Peter
text: <td> male
text: <td> 34
text: <td> Susanne
text: <td> female
text: <td> 12
male: <td text="male"> male

answered Dec 15, 2019 at 18:56

Gerold Broser's user avatar

Gerold BroserGerold Broser

13.9k4 gold badges48 silver badges103 bronze badges

Excellent answers all around, but I think I can add something that worked for me in a practical scenario: exploiting the aria-label attribute for CSS.

For the readers that don’t know: aria-label is an attribute that is used in conjunction with other similar attributes to let a screen-reader know what something is, in case someone with a visual impairment is using your website. Many websites add these attributes to elements with images or text in them, as «descriptors».

This makes it highly website-specific, but in case your element contains this, it’s fairly simple to select that element using the content of the attribute:

HTML:

<td aria-label="male">Male</td>
<td aria-label="female">Female</td>

CSS:

td[aria-label="male"] {
    outline: 1px dotted green;
}

This is technically the same thing as using the data-attribute solution, but this will work for you if you are not the author of the website, plus this is not some out-of-the-way solution that is specifically designed to support this use case; it’s fairly common on its own. The one downside of it is that there’s really no guarantee that your intended element will have this attribute present.

answered Jun 3, 2022 at 9:41

cst1992's user avatar

cst1992cst1992

3,7431 gold badge29 silver badges40 bronze badges

1

Most of the answers here try to offer alternative to how to write the HTML code to include more data because at least up to CSS3 you cannot select an element by partial inner text. But it can be done, you just need to add a bit of vanilla JavaScript, notice since female also contains male it will be selected:

      cells = document.querySelectorAll('td');
    	console.log(cells);
      [].forEach.call(cells, function (el) {
    	if(el.innerText.indexOf("male") !== -1){
    	//el.click(); click or any other option
    	console.log(el)
    	}
    });
 <table>
      <tr>
        <td>Peter</td>
        <td>male</td>
        <td>34</td>
      </tr>
      <tr>
        <td>Susanne</td>
        <td>female</td>
        <td>14</td>
      </tr>
    </table>
<table>
  <tr>
    <td data-content="Peter">Peter</td>
    <td data-content="male">male</td>
    <td data-content="34">34</td>
  </tr>
  <tr>
    <td data-conten="Susanne">Susanne</td>
    <td data-content="female">female</td>
    <td data-content="14">14</td>
  </tr>
</table>

answered Dec 27, 2017 at 20:11

Eduard Florinescu's user avatar

Eduard FlorinescuEduard Florinescu

16.5k28 gold badges112 silver badges178 bronze badges

I agree the data attribute (voyager’s answer) is how it should be handled, BUT, CSS rules like:

td.male { color: blue; }
td.female { color: pink; }

can often be much easier to set up, especially with client-side libs like angularjs which could be as simple as:

<td class="{{person.gender}}">

Just make sure that the content is only one word! Or you could even map to different CSS class names with:

<td ng-class="{'masculine': person.isMale(), 'feminine': person.isFemale()}">

For completeness, here’s the data attribute approach:

<td data-gender="{{person.gender}}">

answered Dec 4, 2017 at 9:37

DJDaveMark's user avatar

DJDaveMarkDJDaveMark

2,57720 silver badges35 bronze badges

1

If you’re using Chimp / Webdriver.io, they support a lot more CSS selectors than the CSS spec.

This, for example, will click on the first anchor that contains the words «Bad bear»:

browser.click("a*=Bad Bear");

answered Feb 2, 2018 at 17:26

Ryan Shillington's user avatar

Ryan ShillingtonRyan Shillington

22.4k14 gold badges91 silver badges106 bronze badges

@voyager’s answer about using data-* attribute (e.g. data-gender="female|male" is the most effective and standards compliant approach as of 2017:

[data-gender='male'] {background-color: #000; color: #ccc;}

Pretty much most goals can be attained as there are some albeit limited selectors oriented around text. The ::first-letter is a pseudo-element that can apply limited styling to the first letter of an element. There is also a ::first-line pseudo-element besides obviously selecting the first line of an element (such as a paragraph) also implies that it is obvious that CSS could be used to extend this existing capability to style specific aspects of a textNode.

Until such advocacy succeeds and is implemented the next best thing I could suggest when applicable is to explode/split words using a space deliminator, output each individual word inside of a span element and then if the word/styling goal is predictable use in combination with :nth selectors:

$p = explode(' ',$words);
foreach ($p as $key1 => $value1)
{
 echo '<span>'.$value1.'</span>;
}

Else if not predictable to, again, use voyager’s answer about using data-* attribute. An example using PHP:

$p = explode(' ',$words);
foreach ($p as $key1 => $value1)
{
 echo '<span data-word="'.$value1.'">'.$value1.'</span>;
}

answered Sep 9, 2017 at 10:09

John's user avatar

If you want to apply style to the content you want. Easy trick.

    td { border: 1px solid black; }
    td:empty { background: lime; }
    td:empty::after { content: "male"; }
    <table>
      <tr>
        <td>Peter</td>
        <td><!--male--></td>
        <td>34</td>
      </tr>
      <tr>
        <td>Susanne</td>
        <td>female</td>
        <td>14</td>
      </tr>
    </table>

https://jsfiddle.net/hyda8kqz/

answered Aug 24, 2021 at 6:58

Arsen's user avatar

ArsenArsen

1237 bronze badges

1

I find the attribute option to be your best bet if you don’t want to use javascript or jquery.

E.g to style all table cells with the word ready, In HTML do this:

 <td status*="ready">Ready</td>

Then in css:

td[status*="ready"] {
        color: red;
    }

answered Apr 9, 2020 at 13:36

Anthony's user avatar

1

Doing small Filter Widgets like this:

    var searchField = document.querySelector('HOWEVER_YOU_MAY_FIND_IT')
    var faqEntries = document.querySelectorAll('WRAPPING_ELEMENT .entry')

    searchField.addEventListener('keyup', function (evt) {
        var testValue = evt.target.value.toLocaleLowerCase();
        var regExp = RegExp(testValue);

        faqEntries.forEach(function (entry) {
            var text = entry.textContent.toLocaleLowerCase();

            entry.classList.remove('show', 'hide');

            if (regExp.test(text)) {
                entry.classList.add('show')
            } else {
                entry.classList.add('hide')
            }
        })
    })

answered Sep 15, 2018 at 21:36

campino2k's user avatar

campino2kcampino2k

1,6101 gold badge14 silver badges25 bronze badges

The syntax of this question looks like Robot Framework syntax.
In this case, although there is no css selector that you can use for contains, there is a SeleniumLibrary keyword that you can use instead.
The Wait Until Element Contains.

Example:

Wait Until Element Contains  | ${element} | ${contains}
Wait Until Element Contains  |  td | male

answered Aug 9, 2019 at 14:26

Eftychia Thomaidou's user avatar

Is there a way to select an element in css based on element text?

ie:

li[text=*foo]

<li>foo</li>
<li>bar</li>

That probably doesn’t work.

Edit: Also only need to support Chrome.

Samuel Liew's user avatar

Samuel Liew

76.1k107 gold badges156 silver badges257 bronze badges

asked Mar 26, 2011 at 10:25

Harry's user avatar

0

I know it’s not exactly what you are looking for, but maybe it’ll help you.

You can try use a jQuery selector :contains(), add a class and then do a normal style for a class.

the Tin Man's user avatar

the Tin Man

158k42 gold badges214 silver badges302 bronze badges

answered Mar 26, 2011 at 10:39

Błażej Klisz's user avatar

Błażej KliszBłażej Klisz

1,7302 gold badges16 silver badges16 bronze badges

3

Not with CSS directly, you could set CSS properties via JavaScript based on the internal contents but in the end you would still need to be operating in the definitions of CSS.

answered Mar 26, 2011 at 10:29

zellio's user avatar

zelliozellio

31k1 gold badge42 silver badges60 bronze badges

2

It was probably discussed, but as of CSS3 there is nothing like what you need (see also «Is there a CSS selector for elements containing certain text?»).
You will have to use additional markup, like this:

<li><span class="foo">some text</span></li>
<li>some other text</li>

Then refer to it the usual way:

li > span.foo {...}

Community's user avatar

answered Mar 26, 2011 at 10:29

Agos's user avatar

AgosAgos

18.4k11 gold badges56 silver badges69 bronze badges

1

#статьи

  • 23 янв 2023

  • 0

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

Иллюстрация: Оля Ежак для Skillbox Media

Антон Сёмин

Пишет об истории IT, разработке и советской кибернетике. Знает Python, JavaScript и немного C++, но предпочитает писать на русском.

Удачный выбор селектора не только позволяет избежать ошибок в коде, но и упрощает вёрстку, поэтому желательно знать разновидности селекторов и хорошо в них ориентироваться. Эта статья будет полезна как новичкам, так и опытным фронтенд-разработчикам и верстальщикам, которые хотят освежить знания.

Содержание

  • Что такое CSS-селекторы
  • Основные виды селекторов
  • Селекторы отношений
  • Селекторы по атрибуту
  • Немного о псевдоклассах
  • Как определить приоритет селектора

Селектор (от англ. select — выбирать) — это шаблон, который позволяет обратиться к элементу или группе элементов веб-страницы, чтобы применить к ним стили CSS. Его указывают перед блоком со свойствами:

a {
		text-decoration: none;
  }

В примере выше селектор указывает на тег <a> (гиперссылка). Так мы говорим браузеру отключить подчёркивание у всех ссылок на странице, устанавливая для свойства text-decoration значение none.

Подключим CSS-стили к следующему HTML-файлу:

<p>Содержание статьи:</p>
	<ul>
		<li><a href="#">Emmet на практике: пишем HTML</a></li>
		<li><a href="#">Создаём шапку документа</a></li>
		<li><a href="#">Подключаем стили и скрипты</a></li>
		<li><a href="#">Добавляем ссылки</a></li>
		<li><a href="#">Вводим теги</a></li>
	</ul>

Вот как она выглядит в браузере:

Страница в браузере
Скриншот: Skillbox Media

Есть ненумерованный список со ссылками, которые браузер по умолчанию выделяет синим цветом и подчёркивает. Если подключить стили, которые мы написали выше, то подчёркивание исчезнет:

Та же страница, но ссылки не подчёркнуты
Скриншот: Skillbox Media

CSS-селектор работает! Но это, конечно, далеко не единственный способ обращения к элементам.

О том, как подключить CSS к HTML, читайте в другой нашей статье.

Структура реальных проектов гораздо сложнее. Веб-страницы интернет-магазинов, корпоративных сайтов и блогов наполнены множеством вложенных и однотипных элементов — всем нужно задать уникальный дизайн. Если бы мы могли обращаться к ним только по названию, то даже с CSS веб оставался бы хранилищем скучного гипертекста.

К счастью, есть около 20 способов выбрать нужный элемент. Рассмотрим основные.

Он применяет стили ко всем элементам страницы и обозначается символом * (звёздочка). С его помощью удобно сбрасывать отступы и задавать значение box‑sizing для всех блочных элементов:

* {
  margin: 0;
  box-sizing: border-box;
}

Этот селектор CSS применяет стили ко всем элементам с одинаковым тегом. Например, для всех <div>, <h2>, <p> и так далее.

Мы уже познакомились с ним, когда убирали подчёркивание у ссылок:

a {
		text-decoration: none;
  }

Селектор по идентификатору обозначается символом # (решётка) и применяет стили к элементу, для которого задан атрибут id с соответствующим значением. При этом у элемента может быть только один id, и этот id должен быть уникальным в пределах веб-страницы.

<p id="intro">Сегодня мы расскажем вам об Emmet.</p> 
<p id="article_content">В этой статье вы узнаете:</p>

CSS-код:

#intro{
		color: red;
		font-weight: bold;
	}

#article_content{
		font-family: sans-serif;
		font-weight: bold;
	}

Текст в блоке p с идентификатором intro окрасится в красный, а текст с идентификатором article_content выделится жирным и получит шрифт без засечек:

Скриншот: Skillbox Media

CSS-селектор по классу выбирает элементы, для которых назначен атрибут class с соответствующим значением. При этом один элемент может принадлежать нескольким классам — в таком случае их перечисляют через пробел:

<p class="plain_text article">Сегодня мы расскажем вам про Emmet.</p> 

Абзац входит в классы plain_text и article. Значит, к нему применяются стили обоих классов:

.plain_text{
		font-size: 20px;
	}

.article{
		font-family: "Montserrat"; 
	}

CSS-селекторы можно сгруппировать, чтобы применить стили к нескольким группам и/или классам элементов. Для этого достаточно перечислить их через запятую:

.plain_text, p, h1, figure, div {
    margin-top: 0;
    margin-left: 0;
}

re>

Есть группа селекторов, которые позволяют выбрать элемент по его отношению к другим элементами (родитель — потомок) и по расположению в DOM (Document Object Model).

Чтобы обратиться ко всем потомкам В элемента A, независимо от уровня их вложенности, используют конструкцию A B (селекторы разделяют пробелом):

figure img {
    margin-bottom: 20px;
}

В примере выше мы устанавливаем всем изображениям внутри элемента figure значение нижних отступов 20 пикселей.

Если нужно применить CSS-стили к потомкам B элемента A только на первом уровне вложенности, то вместо пробела пишут символ >:

.container > img {
    margin-bottom: 40px;
}

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

Селектор A ~ B выбирает все элементы B, которые идут после A. Обратите внимание: «идут после», а не вложены в него. Например, так мы задали цвет фона #f2f3f5 всем карточкам, которые идут после блока из класса .about_us:

.about_us > .card {
    background-color: #f2f3f5;
}

Селектор A + B выбирает только первый элемент B, который следует за A:

.about_us + .card {
    background-color: #f2f3f5;
}

В этом примере цвет фона #f2f3f5 установится только для той карточки, которая идёт сразу после .about_us.

Ещё один полезный инструмент — селекторы по атрибуту. Они позволяют выбрать элемент по имени атрибута, его значению или части значения. Кратко расскажем обо всех.

Применяет стили к элементам, для которых задан этот атрибут:

[title] {
		font-weight: bold;
	}

Работает по имени и значению атрибута:

[title="what_is"] {
		font-weight: normal;
	}

Находит элементы с заданным атрибутом, значение которого начинается с value:

[class^="form"] {
		background-color: #7aacba;
	}

Ищет по названию атрибута и значению, которое равно или начинается с value:

[class|="form"] {
		border: 5px outset black;
	}

Применяет CSS-стили к элементам, у которых значение заданного атрибута оканчивается на value:

[class$="primary"] {
		font-weight: bold;
	}

Селектор по названию атрибута и значению, которое должно содержать value:

[class$="control"] {
		padding: 15px;
	}

Этот шаблон выбирает элементы с атрибутом attr, значение которого состоит из нескольких слов, разделённых пробелом, одно из которых — value:

[class$="control"] {
		padding: 15px;
	}

Псевдокласс выбирает элементы, находящиеся в определённом состоянии или положении в иерархии DOM.

Вот несколько примеров таких состояний:

  • на кнопку наведён курсор мыши;
  • пользователь перешёл или не перешёл по ссылке;
  • курсор установлен на поле ввода.

Например, так с помощью CSS можно увеличить размер ссылок, на которые пользователь навёл курсор:

a:hover {
		font-size: 20px;
	}

Вот как это выглядит в браузере:

Изображение: Skillbox Media

А в следующем примере мы добавляем нижний отступ последнему параграфу-потомку контейнера («Параграф 3»).

<div class="container">
		<p>Параграф 1</p>
		<p>Параграф 2</p>
		<p>Параграф 3</p>
	</div>
	<p>Параграф 4</p>
	<p>Параграф 5</p>

CSS-код:

.container p:last-child {
  		margin-bottom: 30px;
	}

Если зайти в DevTools, то можно увидеть, что под третьим элементом p появилось поле margin (подсвечивается бежевым цветом):

Скриншот: Skillbox Media

Вот список основных псевдоклассов:

Название Состояние элемента
:hover Наведён курсор
:focus Элемент находится в фокусе (например, по нему кликнули мышью или его выбрали клавишей Tab)
:visited Ссылка, которая была посещена
:active Активный элемент (в промежутке времени между нажатием и отпусканием кнопки мыши)
:checked Элементы radio, checkbox или option, которые были выбраны
:first-child Первый потомок элемента
:last-child Последний потомок элемента
:nth-child() Каждый n-й потомок — число n передаётся в качестве аргумента
:last-nth-child() Последние n потомков — число n передаётся в качестве аргумента
:read-write Элементы, доступные для редактирования

Посмотреть другие псевдоклассы можно на сайте Mozilla.

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

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

Специфичность — это показатель, по которому браузер определяет, какие стили применить к элементу. Её можно представить в виде четырёх чисел 0.0.0.0, где каждый разряд — это вес, определяемый специальными правилами.

Вот эти правила:

  • Наивысший приоритет — у стилей, прописанных в атрибуте style (1.0.0.0).
  • На втором месте — селекторы по идентификатору (0.1.0.0).
  • Затем идут три равноправные группы: селекторы по классу, атрибуту и псевдоклассы (0.0.1.0).
  • На четвёртом месте — селекторы по тегу и псевдоэлементы (0.0.0.1).
  • Комбинаторы ~, >, + и универсальный селектор * веса не добавляют.
  • Вес псевдоклассов :is(), :has() и :not() равен весу самого специфичного селектора внутри скобок.

Чтобы определить самый «тяжёлый» селектор, браузер сначала взвешивает каждый, а затем сравнивает их поразрядно.

Попробуем порассуждать как браузер. Допустим, на странице есть элемент, на который указывают два CSS-селектора:

.container div ul  {/**/} 
#our_team div.developers  {/**/} 

Рассчитаем их вес:

  • Класс .container добавляет 1 в третий разряд, а div и ul — по единице в четвёртый. Результат: 0.0.1.2.
  • Идентификатор our_team добавляет 1 во второй разряд, тег div — 1 в четвёртый разряд, а класс .developers — 1 в третий. Получаем 0.1.1.1.

Браузер применит стили селектора #our_team div.developers, потому что он указывает на идентификатор (см. правило №2 в списке).

А если бы исследуемый элемент обладал атрибутом style, то и считать ничего бы не пришлось. Ведь, как мы уже знаем, style обладает наивысшим приоритетом:

<a style="color: red;" class="article media code" id="definition">Программист — это...</p>

А теперь секретный приём. Вы можете перебить любое правило, если добавите к нему ключевое слово !important. В таком случае стили намертво приклеятся к элементу:

a {
		font-weight: bold !important;
	}

После этого изменить начертание текста в ссылках можно будет, только если использовать !important в более специфическом селекторе. Например, таком:

#stronger a {
		font-weight: normal !important;
	}

Опытные разработчики не рекомендуют использовать !important, потому что это усложняет поддержку кода и ломает каскад. Поэтому просто помните о его существовании во время дебаггинга: возможно, это словечко спряталось где-то в документе styles.css.

CSS предоставляет большое количество селекторов для удобной стилизации веб-страниц. Запомните их и используйте всё разнообразие, чтобы писать понятный и легко поддерживаемый код. А закрепить знания можно в замечательной браузерной игре CSS Dinner.

Научитесь: Профессия Frontend-разработчик
Узнать больше

На этом уроке мы изучим основные виды селекторов, и научимся их использовать на практике.

Что такое CSS селекторы

селектор {
  свойство: значение;
  свойство: значение;
  ...
}  

Селекторы — это один из фундаментальных механизмов CSS. Именно они определяют то, к каким элементам будут применены стили, указанные в фигурных скобках.

Пример CSS правила:

p {
  text-align: center;
  font-size: 20px;
}

В этом CSS правиле, p — это селектор, в данном случае — это селектор элемента. Это CSS правило устанавливает стили (CSS свойства, описанные в нём) для всех элементов p на странице.

В CSS очень много различных типов селекторов. Используя один из них или комбинацию из нескольких можно очень точно применить стили к нужным элементам.

Базовые селекторы

К базовым селекторам можно отнести селектор по классу, тегу, идентификатору, атрибуту и универсальный селектор.

Селектор по элементу (тегу)

Селектор по элементу предназначен для выбора элементов по имени тега.

Синтаксис: имяТега

Пример задания правила для всех элементов p на странице:

/* селектор p выберет все элементы p на странице */
p {
  padding-bottom: 15px;
}

Селектор по классу

Селектор по классу предназначен для выбора элементов по классу (значению атрибута class).

Синтаксис: .имяКласса

Пример задания правила для всех элементов, имеющих класс center:

/* селектор .center выберет все элементы, имеющие класс center */
.center {
  text-align: center;
}

Селектор по идентификатору (id)

Селектор по идентификатору предназначен для выбора элемента по идентификатору (значению атрибута id).

Синтаксис: #имяИдентификатора

Пример задания правила для элемента, имеющего в качестве значения атрибута id значение footer:

/* селектор #footer выберет элемент, имеющий идентификатор footer */
#footer {
  height: 50px;
  margin-top: 20px;
}

Универсальный селектор

Универсальный селектор (селектор звёздочка) предназначен для выбора всех элементов.

Синтаксис: *

Пример задания правила для всех элементов на странице:

/* селектор * выберет все элементы на странице */
* {
  margin: 0;
  padding: 0;
}

CSS селекторы по атрибуту

Селекторы по атрибуту предназначены для выбора элементов по имени атрибута и (или) его значению.

Типы селекторов по атрибуту:

  • [attr] – по имени атрибута;
  • [attr=value] – по имени и значению атрибута;
  • [attr^=value] – по имени и значению, с которого оно должно начинаться;
  • [attr|=value] – по имени атрибута и его значению, которое равно value или начинается со value-;
  • [attr$=value] – по имени атрибута и значению, на которое оно должно заканчиваться;
  • [attr*=value] – по указанному атрибуту и значению, которое должно содержать value;
  • [attr~=value] – по имени атрибута и значению, которое содержит value отделённое от других с помощью пробела.

[attr]

Пример задания правила для всех элементов на странице, имеющих атрибут target:

/* селектор [target] выберет все элементы на странице, имеющих атрибут target */
[target] {
  background-color: red;
}

[attr=value]

Пример задания правила для всех элементов на странице, имеющих атрибут rel со значением nofollow:

/* селектор [rel="nofollow"] выберет все элементы на странице, имеющих атрибут rel со значением nofollow */
[rel="nofollow"] {
  background-color: green;
}

[attr^=value]

Пример задания правила для всех элементов на странице, имеющих атрибут class, значение которого начинается с col:

/* селектор [class^="col"] выберет все элементы на странице, имеющих атрибут class, значение которого начинается с col */
[class^="col"] {
  background-color: yellow;
}

[attr|=value]

Пример задания правила для всех элементов на странице, имеющих атрибут class, значение которого равно test или начинается с test- (т.е. с обязательным дефисом, после которого идёт остальное содержимое значения):

/* селектор [class|="test"] выберет все элементы на странице, имеющих атрибут class, значение которого равно test или начинается с test- */
[class|="test"] {
  background-color: orange;
}

[attr$=value]

Пример задания правила для всех элементов на странице, имеющих атрибут class, значение которого заканчивается на color:

/* селектор [class$="color"] выберет все элементы на странице, имеющих атрибут class, значение которого заканчивается на color */
[class$="color"] {
  background-color: yellow;
}

[attr*=value]

Пример задания правила для всех элементов на странице, имеющих атрибут href, значение которого содержит подстроку youtu.be (например будет выбран элемент, если атрибут href у него равен https://youtu.be/TEOSuiNfUMA):

/* селектор [href*="youtu.be"] выберет все элементы на странице, имеющих атрибут href, значение которого содержит youtu.be */
[href*="youtu.be"] {
  background-color: green;
}

[attr~=value]

Пример задания правила для всех элементов на странице, имеющих атрибут data-content, значение которого содержит news, отделённое от других с помощью пробела (например будет выбран элемент, если у него атрибут data-content равен hot-news news news-football):

/* селектор [data-content~="news"] выберет все элементы на странице, имеющих атрибут data-content, значение которого содержит news, отделённое от других с помощью пробела */
[data-content~="news"] {
  background-color: brown;
} 

Псевдоклассы

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

Псевдоклассы — это дополнение к основному селектору, которое позволяет выбрать элемент в зависимости от его особого состояния. Добавляется он к селектору c помощью символа :, т.е. так селектор:псевдокласс.

Псевдоклассы для выбора элементов в зависимости от их состояния

К этой группе псевдоклассов можно отнести псевдоклассы: :link, :visited, :hover, :active и :focus.

Псевдоклассы :link и :visited предназначены исключительно для ссылок (элементов a с атрибутом href).

Псевдоклассы :hover, :active и :focus могут применяться не только к ссылкам, но и к другим элементам.

Псевдокласс :link

Псевдокласс :link предназначен для выбора не посещённых ссылок.

Пример задания правила для всех элементов a с классом external, которые пользователь ещё не посетил:

/* селектор a.external:link выберет все элементы a с классом external пользователь по которым ещё не переходил */
a.external:link {
  color: red;
}

Псевдокласс :visited

Псевдокласс :visited предназначен для выбора посещённых ссылок.

Пример задания правила для всех элементов a, расположенных в .aside, пользователь которые уже посетил:

/* селектор .side a:visited выберет все элементы a, находящиеся в .aside, пользователь которые уже посетил */
.aside a:visited {
  color: #000;
}

Псевдокласс :active

Псевдокласс :active предназначен для выбора элементов в момент когда они активируются пользователем. Например, когда пользователь нажал левой кнопкой мышкой на ссылку, но её ещё не отпустил. В основном данный класс применяется для ссылок (a) и кнопок (button), но может также использоваться и для других элементов.

Пример задания CSS правила для всех элементов a когда они активируются пользователем:

/* селектор a:active выберет все элементы a, находящиеся в активном состоянии */
a:active {
  background-color: yellow;
}

Псевдокласс :hover

Псевдокласс :hover предназначен для выбора элементов при поднесении к ним курсора (при наведении на них).

Пример задания CSS правила для всех элементов .btn-warning при поднесении к ним курсора:

/* селектор .btn-warning:hover выберет все элементы .btn-warning при поднесении к ним курсора */
.btn-warning:hover {
  color: #fff;
  background-color: #ff8f00;
}

При задании CSS-правил для ссылок с использованием псведоклассов :link, :visited, :hover и :active, их следует распологать в следеующем порядке:

a:link { ... }
a:visited { ... }
a:hover { ... }
a:active { ... }

Если CSS-правила расположить в другом порядке, то часть из них могут не работать.

Псевдокласс :focus

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

Пример задания CSS правила для элемента input[type="text"] при нахождении его в фокусе:

/* селектор input[type="text"] найдет элемент input с атрибутом type="text" при нахождении его в фокусе */
input[type="text"]:focus {
  background-color: #ffe082;
}

По расположению среди соседей

При выборе элементов можно дополнительно с помощью псевдоклассов задать условие (фильтр) по их расположению (порядковому номеру) в родителе.

Псевдоклассы, предназначенные для этого: :first-child, :last-child, :only-child, :nth-child(выражение), :nth-last-child(выражение).

Псевдокласс :first-child

Псевдокласс :first-child применяется для выбора элементов, которые являются первыми дочерними элементами своего родителя.

Пример задания CSS правила для элементов li являющимися первыми дочерними элементами своего родителя:

/* селектор li:first-child выберет элементы li, которые являются первыми элементами своего родителя */
li:first-child {
  font-weight: bold;
}

Псевдокласс :last-child

Псевдокласс :last-child применяется для выбора элементов, которые являются последними дочерними элементами своего родителя.

Пример задания CSS правила для элементов .alert-warning, которые являются последними дочерними элементами своего родителя:

/* селектор .alert-warning:last-child выберет элементы .alert-warning которые являются последними элементами своего родителя */
.alert-warning:last-child {
  font-weight: bold;
}

Псевдокласс :only-child

Псевдокласс :only-child используется для выбора элементов, если они являются единственными дочерними элементами внутри родительского контейнера.

Например:

h2:only-child {
  ...
}

Селектор h2:only-child выберет все элементы h2, если они являются единственными дочерними элементами своего родителя.

Действие аналогичное :only-child можно выполнить с помощью псевдоклассов :first-child и :last-child. Например селектор h2:only-child можно ещё реализовать так: h2:last-child:first-child.

Псевдокласс :nth-child(выражение)

Псевдокласс :nth-child() применяется для выбора элементов по их порядковому номеру в родителе. В качестве выражения можно использовать число, формулу или ключевые слова odd или even. Отсчёт элементов в родителе начинается с 1.

Например:

/* селектор .li:nth-child(2) выберет элементы li, которые явлются вторыми элементами своего родителя */
.li:nth-child(2) { ... }
/* селектор .li:nth-child(odd) выберет элементы li, которые явлются нечётными элементами (1, 3, 5, ...) своего родителя */
.li:nth-child(odd) { ... }
/* селектор .li:nth-child(even) выберет элементы li, которые явлются чётными элементами (2, 4, 6, ...) своего родителя */
.li:nth-child(even) { ... }
/* селектор .li:nth-child(2n+1) выберет элементы li, которые имеют порядковые номера 1, 3, 5, 7, ... внутри своего родителя */
.li:nth-child(2n+1) { ... }

Формула имеет следующую запись: An + B. A и B — это числа, а n — счетчик, принимающий целые значения, начиная с 0 (т.е. 0, 1, 2, 3 …).

Например, формула вида 3n + 2 будет определять элементы с порядковыми номерами (2, 5, 8, …). Т.е. 3 * 0 + 2, 3 * 1 + 2, 3 * 2 + 2, …

А например, формула вида 5n будет определять элементы с порядковыми номерами (0, 5, 10, …). Т.е. 5 * 0, 5 * 1, 5 * 2, …

Псевдокласс :nth-last-child(выражение)

Псевдокласс :nth-last-child() выполняет те же действия что и :nth-child() за исключением того, что отсчет элементов в родителе вёдется не с начала, а с конца. В псведоклассе :nth-last-child(выражение) в качестве выражения можно использовать те же вещи, т.е. число, формулу, или ключевые слова odd или even

По расположению среди соседей с учётом типа элемента

В CSS имеются псевдоклассы аналогичные :first-child, :last-child и т.д. Они отличаются от них только тем, что выполняют это с учётом типа элемента.

Список псевдоклассов, предназначенных для этого: :first-of-type, :last-of-type, :only-of-type, :nth-of-type(выражение), :nth-last-of-type(выражение).

Псевдокласс :first-of-type

Данный псевдокласс очень похож на :first-child, но в отличие от него он выбирает не просто первый элемент, а первый элемент своего родителя с учётом его типа.

Например, выберем все элементы p, которые являются первыми элементами указанного типа у своего родителя:

p:first-of-type {
  ...
}

HTML:

<section>
  <h2>...</h2>
  <p>...</p> <!-- будет выбран этот элемент -->
  <p>...</p>  
</section>
<section>
  <h2>...</h2>
  <p>...</p> <!-- будет выбран этот элемент -->
  <p>...</p>  
</section>

При использовании селектора p:first-child, ни один элемент p не был выбран, т.к. ни один из них не является первым дочерним элементом своего родителя.

Псевдокласс :last-of-type

Данный псевдокласс предназначен для выбора элементов, которые являются последними дочерними элементами данного типа своего родителя.

Пример записи:

li:last-of-type {
  ...
}  

Псевдокласс :only-of-type

Псевдокласс :only-of-type применяется для выбора элементов, если каждый из них являются единственным дочерним элементом данного типа внутри своего родителя. В отличие от :only-child псведокласс :only-of-type работает аналогично, но с учётом типом элемента.

Пример:

p:only-of-type {
  ...
}

В этом примере стили будут применены к элементам p, которые являются единственным элементом p внутри своего родителя.

Псевдокласс :nth-of-type(выражение)

Данный псевдокласс предназначен для выбора элементов по их порядковому номеру в родителе с учетом их типа.

Псевдокласс :nth-of-type(выражение) похож на :nth-child(выражение) с разницей лишь а том, что он учитывает тип элемента. В качестве выражения также можно использовать число, формулу или ключевые слова odd или even. Отсчёт элементов в родителе начинается с 1.

Например:

<section>
  <h2>...</h2>
  <p>...</p> <!-- Селектор p:nth-child(2) выберет этот элемент -->
  <p>...</p> <!-- Селектор p:nth-of-type(2) выберет этот элемент -->
</section>

Селектор p:nth-child(2) выберет второй по счёту элемент, если он является p, а селектор p:nth-of-type(2) веберет второй дочерний элемент p среди дочерних p.

Псевдокласс :nth-last-of-type(выражение)

Псевдокласс :nth-last-of-type(выражение) аналогичен классу :nth-of-type(выражение) с разницей в том, что отсчёт дочерних элементов ведётся с конца.

Псевдоклассы для элементов форм

К этой группе можно отнести псевдоклассы :enabled, :disabled и :checked.

Псевдоклассы этой группы, а также :hover, :active и :focus ещё называют событийными селекторами, т.к. они позволяют применить стили при наступлении определённых событий.

Псевдокласс :checked

Псевдокласс :checked предназначен для выбора элементов radio, checkbox и option внутри select, которые находятся во включенном состоянии.

Пример:

<div class="form-group">
  <input type="checkbox" id="answer-1">
  <label for="answer-1">Я знаю что такое :checked</label>
</div>  

CSS:

input:checked + label {
  background-color: yellow;
}  

В этом примере фон элемента label при отмеченном checkbox выделяется цветом. Выбор включенного чекбокса выполняется с помощью псевдокласса :checked.

Псевдокласс :enabled

Псевдокласс :enabled предназначен для выбора включенных элементов формы, с которыми пользователь может взаимодействовать, например, нажать на него или внести текст.

Пример, в котором установим для всех включенных элементов input фон:

input:enabled {
  background-color: yellow;
}  

Псевдокласс :disabled

Элементы формы могут кроме включенного состояния находиться ещё в отключенном.

Псевдокласс :disabled предназначен для выбора отключенных элементов формы, т.е. элементов с которыми пользователь в данный момент не может взаимодействовать.

Например, выберем все отключенные элементы input:

input:disabled {
  ...
}

Остальные псевдоклассы

Псевдокласс :not(селектор)

Псевдокласс :not() предназначен для выбора элементов, которые не содержат указанный селектор.

Например:

/* Селектор .aside > div:not(:first-child) выберет все элементы div кроме первого непосредственно расположенные в .aside */
.aside > div:not(:first-child) { ... }

В качестве селектора можно указывать селекторы по тегам, классам, атрибутам, использовать псевдоклассы, т.е. всё кроме псведокласса :not(), несколько сгруппированных селекторов, псевдоэлементы, дочерние и вложенные селекторы:

/* такие конструкция работать не будет */
:not(:not(...)) { ... }
div:not(.alert.alert-warning) { ... }
.item:not(::before) { ... }
.slider .slider__item:not(.active img) { ... }
td:not(.row + td) { ... }

При необходимости можно использовать несколько псевдоклассов :not().

Например:

/* применим стили ко всем элементам div, расположенных непосредственно в .message, за исключением .alert-warning и .alert-danger */
.message > div:not(.alert-warning):not(.alert-danger) { ... }

Пример CSS селектора для выбора элементов, которые не содержат некоторый класс:

// этот селектор выберет все элементы p, которые не содержат класс alert
p:not(.alert) {
  ...
}

Псевдокласс :empty

Псевдокласс :empty предназначен для выбора пустых элементов (т.е. элементов, у которых нет дочерних узлов, в том числе текстовых).

Пример:

div:empty {
  ...
}

Селектор div:empty выберет все пустые элементы div на странице.

Псевдокласс :root

Псевдокласс :root предназначен для выбора корневого элемента документа. В HTML документе данным элементом является <html>. В отличие от селектора по тегу html данный псевдокласс имеет более высокий приоритет.

Применять :root можно например для объявления CSS переменных:

:root {
  --text-info: hotpink;
  --text-warning: hotpink;
  --aside-padding: 10px 15px;
}

Псевдокласс :target

Псевдокласс :target предназначен для выбора элемента, идентификатор которого соответствует хэшу в URL-адресе.

Например:

<h2 id="header-1">...</h2>
<h2 id="header-2">...</h2>

CSS-правило:

:target {
  color: red;
}

В этом примере стили будут применены к элементу с id="header-1", если хэш URL страницы будет равен #header-1. Если же хэш будет равен #header-2, то псевдокласс :target соответственно выберет элемент с id="header-2" и стили уже будут применены к нему.

Группировка селекторов

Для задания правил нескольким селекторам одновременно их необходимо перечислить через запятую.

Синтаксис: селектор1, селектор2, …

Пример задания правила для всех элементов h3 и h4 на странице:

/* селектор h3, h4 выберет все элементы на странице, имеющих тег h3 и h4 */
h3, h4 {
  font-size: 20px;
  margin-top: 15px;
  margin-bottom: 10px;
}

Комбинирование селекторов

В CSS селекторы можно комбинировать. Осуществляется это очень просто, посредством последовательного их записывания, без использования пробела.

Пример селектора для выбора элементов, которые имеют одновременно два класса:

.modal.open {
  ...
}  

Пример селектора для выбора элементов, которые имеют указанный класс, атрибут, и является первым дочерним элементом в своём родителе:

.btn[data-toggle="collapse"]:first-child { ... }

Селекторы отношений

В HTML документе каждый элемент всегда связан с другими элементами.

Виды отношений между HTML элементами:

  • родитель – элемент, непосредственно в котором находится рассматриваемый элемент;
  • предок – это элемент, который расположен на одном из уровней иерархии элементов, до которого можно дойти двигаясь от рассматриваемого элемента к его родителю, от его родителя к родителю его родителя и т.д.
  • дети – это элементы, непосредственно расположенные в текущем рассматриваемом элементе;
  • потомки (дочерние элементы) – это любые элементы, которые находятся в текущем элементе вне зависимости от уровня иерархии, в котором они расположены;
  • соседи (сиблинги) – это элементы, расположенные на том же уровне вложенности (иерархии), что и рассматриваемый элемент; или другими словами — это все другие элементы, которые имеют того же родителя что и текущий рассматриваемый элемент.

Более наглядно про отношения элементов приведено на рисунке. На этом рисунке отношения рассмотрены относительно элемента выделенного синим цветом.

Виды отношений между HTML элементами

В CSS имеется 4 вида селекторов отношений.

Первые два из них X Y и X > Y относятся к вложенным селекторам. Они предназначены для поиска элементов в зависимости от их нахождения внутри других.

Остальные два X + Y и X ~ Y являются CSS селекторами для выбора соседних элементов.

Эти селекторы называют составными или комбинацией селекторов. Так как они на самом деле состоят из нескольких селекторов, разделённых между собой с помощью специальных символов (комбинаторов). Всего различают 4 символа: пробел, знак > (больше), знак + и ~ (тильда).

Селектор X Y (для выбора вложенных или дочерних элементов)

Селектор X Y (предок потомки) предназначен для выбора элементов Y, находящихся в X.

Другими словами, селектор X Y предназначен для выбора элементов Y, являющихся потомками элементов определяемым селектором X.

Селекторы X Y называют контекстными или вложенными.

Например, селектор дочерних элементов div p выберет все элементы p, расположенные в div.

Селектор X > Y

Селектор X > Y (родитель > дети) предназначен для выбора элементов, определяемым селектором Y непосредственно расположенных в элементе, определяемым селектором X.

По другому можно сказать, что селектор X > Y предназначен для выбора Y, у которых родителем является элемент, определяемым X.

Например, комбинация селекторов li > ul выберет все элементы ul, которые непосредственно расположены в li.

Селектор X + Y

Селектор X + Y предназначен для выбора элементов Y, каждый из которых расположен сразу же после X. Элементы определяемым селектором X и Y должны находиться на одном уровне вложенности, т.е. быть по отношению друг к другу соседями (сиблингами).

Например, комбинация селекторов input + label выберет все элементы label, которые расположены сразу же за элементом input, и являющиеся друг по отношению к другу соседями (сиблингами).

Селектор X ~ Y

Селектор X ~ Y предназначен для выбора элементов Y, которые расположены после X. При этом элементы, определяемые селектором X и Y, должны являться по отношению друг к другу соседями (сиблингами).

Например, p ~ span выберет все элементы span, расположенные после элемента p на том же уровне вложенности.

Приоритет селекторов

Когда в CSS имеется несколько правил, устанавливающих одно и тоже CSS свойство некоторому элементу, приоритетным из них является то, в котором селектор имеет большую специфичность (вес).

Специфичность селекторов удобно представлять в виде 4 чисел: 0,0,0,0.

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

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

Как считать эти цифры? Каждый селектор в зависимости от типа имеет вес:

  • универсальный селектор (не добавляет вес) – 0,0,0,0;
  • селекторы по тегу, псевдоэлемент добавляют единичку к четвёртой цифре – 0,0,0,1;
  • селекторы по классу и по атрибуту, псевдоклассы добавляют единичку ко третьей цифре – 0,0,1,0;
  • селектор по идентификатору добавляют единичку ко второй цифре – 0,1,0,0;

Стили, расположенные в атрибуте style элемента, являются более специфичными по сравнению с селекторами. Вес этих стилей определяется единицей в первой цифре – 1,0,0,0.

Например:

  • *0,0,0,0;
  • li0,0,0,1;
  • li::before0,0,0,2;
  • ul > li0,0,0,2;
  • div input+label0,0,0,3;
  • h1 + div[data-target]0,0,1,2;
  • .btn.show0,0,2,0;
  • ul li a.item0,0,1,3;
  • #aside div.show0,1,1,1;
  • style="..."1,0,0,0;

Повысить важность определённого CSS свойства можно с помощью ключевого слова !important. В этом случае будет использоваться именно данное CSS-свойство.

Например:

<div class="alert-warning" style="background-color: #ffc107;"> ... </div>

В CSS:

.alert-warning {
  background-color: #ffa000 !important;
}

В этом примере элементу будет установлен тот фон к которому добавлено слово !important. !important перебивает любой вес.

Интересный случай, когда нужно определить какое значение CSS-свойства будет применено к элементу, если !important добавлено к нескольким из них.

В этом случае будет применено то значение CSS-свойства c !important у которого больше вес селектора.

К примеру, если добавить !important к CSS-свойству расположенному в style, то получим максимальную возможную специфичность, которую уже никак не перебьёшь.

Например:

<p id="message" style="font-size: 20px !important;">...</p>

CSS:

p#message {
  font-size: 16px !important;
}

В этом примере к элементу #message будет применено CSS-свойство font-size со значением 20px, т.к. хоть у каждого из них имеется состояние !importants, но специфичность style (1,0,0,0) больше чем у селектора p#message (0,1,0,1).

Каких селекторов нет в CSS

В CSS нет селектора для получения родительского элемента. Этот селектор может появиться в новой спецификации CSS, но в CSS3 так выбрать элемент нельзя.

Понравилась статья? Поделить с друзьями:
  • Как найти сайт на страницах поиска
  • Как составить закон конкурс
  • Как исправить имя в карточке
  • Как на карте мегафон найти человека по
  • Как составить резюме на должность специалиста