Css parent: Is there a CSS parent selector?

Содержание

Почему у нас нет селектора по родителю — Веб-стандарты

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

Вкратце: производительность.

Как работает CSSСкопировать ссылку

В связи с моей работой я делаю много тестов производительности. Для определения «узких мест» мы используем массу приложений. Например, Google Page Speed, который дает рекомендации по улучшению производительности JavaScript и рендеринга. Прежде чем я перейду к рассмотрению этих рекомендаций, нам нужно разобраться как браузеры работают с CSS

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

Мы часто рассматриваем веб-страницы как полноценные документы, наполненные элементами и содержимым. Между тем, браузеры разработаны так, чтобы обрабатывать документ потоково. Они начинают получать документ с сервера и могут начать его отображать до момента полной загрузки. Каждый узел анализируется и отображается в окне по мере получения.

Взгляните на этот документ:

<body>
    <div>
        <div>
            <p>Lorem Ipsum</p>
        </div>
        <div>
            <p>Lorem Ipsum</p>
            <p>Lorem Ipsum</p>
            <p>Lorem Ipsum <span>Test</span></p>
        </div>
    </div>
</body>

Браузер начинает сначала и видит элемент <body>. В этот момент времени считается, что этот узел не имеет дочерних узлов. Ничего более не рассматривается. Браузер определяет соответствующий ему обобщенный набор стилей и применяет его к элементу. Какой шрифт, цвет, интерлиньяж? После того, как это все будет выяснено, элемент отображается на экране.

Далее браузер видит элемент <div> со значением атрибута ID content. И снова в этот момент времени браузер считает его пустым. Он не рассматривает другие элементы. Как только браузер рассчитает стиль, элемент отображается на экране. Затем браузер определяет нужно ли перерисовать <body> — стал ли элемент шире или выше? Я подозреваю, что там есть масса других проверок, но изменение ширины и высоты — самый распространенный способ повлиять на отображение родительского узла.

Процесс продолжается, пока браузер не достигнет корневого узла документа.

Вот как выглядит визуализация процессов перерисовки в Firefox:

CSS-селекторы анализируются справа налевоСкопировать ссылку

Чтобы определить, применяется ли CSS-правило к определенному элементу, браузер рассматривает селектор справа налево.

Если у вас есть селектор body div#content p { color: #003366; }, то, когда каждый элемент появляется на странице, браузер проверяет, является ли он параграфом. Если да, он начинает подниматься вверх по DOM и ищет <div> со значением атрибута ID равным content. Если он его находит, то продолжает подниматься по DOM пока не найдет <body>.

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

ПравилаСкопировать ссылку

Возвращаясь к Page Speed, давайте рассмотрим несколько его рекомендаций:

  • Избегайте селектора по потомку: .content .sidebar;
  • Избегайте селектора по дочернему элементу: .content > .sidebar и селектора по следующему элементу: .content + .sidebar.

Конечно, селекторы по ID — самые быстрые. Проверить применимость селектора #content к рассматриваемому элементу можно очень быстро. Есть у него этот ID или нет? Селекторы по классу практически такие же быстрые, так как нет никаких связанных элементов, которые надо проверять.

Селекторы по потомкам, такие как .content .sidebar — более ресурсоемкие, так как, чтобы определить надо ли применять правило к .sidebar, браузер должен найти .content. Cелектор по дочернему элементу, например, .content > .sidebar, лучше селектора по потомку, так как браузер должен проверить только один элемент вместо множества. (К сожалению, селекторы + и > не поддерживаются IE6. Так что если его поддержка актуальна для вас, то про них придется забыть — прим. переводчика).

Селектор по тегу и универсальный селекторСкопировать ссылку

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

Рассмотрим следующий пример:

#content * { color: #039; }

Так как в селекторе присутствует ID, то можно подумать, что этот селектор обрабатывается очень быстро. Проблема в том, что браузер обрабатывает селектор справа налево и сперва проверяется универсальный селектор. Для того чтобы браузер мог определить, должен ли цвет текста элемента быть тёмно-синим, надо проверить каждый предок элемента, пока не будет найден предок с атрибутом ID равным content или не будет достигнут корень документа.

И это должно быть сделано для каждого элемента на странице.

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

Почему IE долго не поддерживал

:last-childСкопировать ссылку

Все жаловались: у всех браузеров, кроме IE, есть поддержка

:last-child (она появилась только в IE9!) Некоторые могли подумать насколько же сложнее сделать :last-child, если уже реализован :first-child?

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

. module > p:first-child { color: red; } /* Первое правило */
.module > p:last-child { color: blue; } /* Второе правило */

Когда мы рассматриваем внутренности первого <div>, мы видим, что там есть параграф. Браузер видит что-то вроде этого:

<div>
    <p>Lorem Ipsum</p>

Нужно ли применить первое правило к параграфу? Да, это параграф; да, это первый дочерний узел; и, да, это непосредственный потомок элемента с классом module.

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

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

Как на самом деле это делает браузер?Скопировать ссылку

Я не мог сказать с абсолютной уверенностью, как браузеры парсят :last-child, так что я создал несколько тестов:

  • Статическая HTML-страница;
  • Рендеринг с паузами в одну секунду.

Первый пример весьма скучен. В любом браузере, включая IE9, всё отображается корректно. Внутри <div> первый элемент красный, а последний синий. Но посмотрите на второй пример, и вы увидите интересные отличия в поведении браузеров.

Второй пример приостанавливается перед добавлением каждого параграфа в <div>.

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

В Safari, Chrome и Opera мы увидим другой подход. Первый параграф красный. Второй отображается чёрным. Последний параграф отображается чёрным, пока браузер не получит закрывающий тег </div>. В этот момент последний параграф становится синим. Эти браузеры не рассматривают элемент как последний, пока не будет закрыт родительский.

В Internet Explorer 9 Beta я нашел интересный баг. В то время, как статическая страница отображается корректно, версия с паузами отрабатывает с любопытным побочным эффектом. Первый параграф синий, второй параграф синий и затем — третий. Когда закрывающий тег </div> загружен, предпоследний параграф меняет цвет на чёрный. IE9 пытается обрабатывать селектор как WebKit и Opera, но… м-м… не выходит. Надо бы отправить багрепорт в Microsoft.

Почему у нас нет селектора по родителю?Скопировать ссылку

Уже дано достаточно пояснений, чтобы можно было вернуться к оригинальному вопросу. Проблема не в том, что у нас не может быть селектора по родителю. Проблема в том, что мы столкнемся с проблемами быстродействия, когда дело дойдет до определения того, какие CSS-правила применимы к данному элементу. Если Google Page Speed не рекомендует использование универсальных селекторов, то можно гарантировать, что селектор по родителю будет первым в списке ресурсоемких селекторов, намного опережая все проблемы с производительностью, которые могут быть вызваны использованием универсального селектора.

Давайте посмотрим почему. Первым делом давайте приведём пример синтаксиса для селектора по родителю.

div.module:has(span) { color: green; }

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

Посмотрите на часть нашего документа:

<div>
    <p>Lorem Ipsum</p>
    <p>Lorem Ipsum</p>
    <p>Lorem Ipsum <span>Test</span></p>
</div>

Исходя из того, что мы видим, .module будет отображён без использования правила, применяемого селектором по родителю. Когда будет загружен первый элемент <p>, нужно повторно оценить применимость селектора по родителю к <div>. Нужно сделать это снова для следующего параграфа. И снова, для следующего. Наконец, когда <span> загружен, селектор по родителю будет применен к родительскому <div>, и элемент нужно будет повторно перерисовать.

И что теперь? Теперь, если изменится любое наследуемое CSS-свойство, каждый потомок должен будет повторно анализироваться и перерисовываться. Ох…

Почему проблему можно решить с помощью JavaScript?Скопировать ссылку

Это только кажется, что JavaScript решает проблему. В общем случае JavaScript-заплатки (заплатки — polyfills — части кода, обеспечивающие функциональность, которую должен обеспечивать браузер — прим. переводчика). Или регрессивное усовершенствование (или как там вы, молодежь, это сейчас называете) запускаются только один раз, после полной загрузки DOM.

Для того чтобы действительно имитировать поведение CSS, любой скрипт, решающий эту проблему, должен запускаться после отображения каждого элемента на странице, чтобы определить, нужно ли применить нашу «заплатку». Помните CSS-expressions в Internet Explorer? Именно по этой причине они вызывали такие проблемы с производительностью.

Не невозможноСкопировать ссылку

Появится ли когда-нибудь селектор по родителю? Возможно. То, что я описал, не невозможно. На самом деле — наоборот. Это значит только то, что нам придётся иметь дело с ухудшением производительности из-за использования этого селектора.

css — content — expand child div to parent height



Высота родительского div равна нулю, даже если у него есть ребенок с конечными высотами

(2)

У меня есть веб-сайт, макет которого показан на диаграмме. Тело состоит из main container , который содержит header , parent div и footer . parent div дополнительно содержит несколько child div как показано.

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

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

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

Прошу прокомментировать, если я неясен, задавая свои сомнения!


Попробуйте добавить в таблицу стилей следующее:

#parentdiv:after { 
    content: " "; 
    display: block;
    clear: both;
} 

Как сказал Дэдал в своем комментарии, вы, вероятно, плаваете с дочерними div. Если это так, строка выше исправляет это.

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

Строка выше создает и вставляет (псевдо) элемент в #parentdiv, который проталкивается мимо всех плавающих div. Затем родительский div, который, несмотря на игнорирование плавающих дочерних элементов, не игнорирует этот псевдоэлемент — действуя так, как должен, он расширяется, чтобы содержать псевдоэлемент. Теперь, поскольку псевдоэлемент находится ниже всех всплывающих дочерних элементов, родительский div происходит или, еще лучше, кажется, «содержит» также и плавающих детей, что и есть то, что вы хотите.


Похоже, у вас есть случай для класса clearfix .

Поэтому я предполагаю, что вы плаваете дочерний div, и поэтому высота родительского div равна 0. Когда вы используете float, родитель не адаптируется к высоте детей.

Но добавив класс clearfix (конечно, вы должны иметь его в своей таблице стилей), он добавит ‘.’ в конце (невидимым, конечно), и ваш родитель будет магически иметь правильную высоту.

Обратите внимание: это кросс-платформенный, совместимый IE6 +, Chrome, Safari, Firefox, вы называете это!

.clearfix:after {
    content: ".";
    display: block;
    clear: both;
    visibility: hidden;
    line-height: 0;
    height: 0;
}
.clearfix {
    display: inline-block;
}
html[xmlns] .clearfix {
    display: block;
}
* html .clearfix {
    height: 1%;
}

как работает селектор CSS

CSS означает каскадные таблицы стилей , что в основном означает, что более поздние элементы на странице имеют приоритет над более ранними (с некоторыми важными оговорками). Это также относится к тому, как мы выбираем элементы — от родителя к дочернему, без возможности выбора родителей,

до настоящего момента .

В спецификации CSS Selectors 4 CSS представляет новый селектор под названием :has() , который, наконец, позволяет нам выбирать родителей. Это означает, что мы сможем настроить таргетинг на элемент CSS, который имеет конкретных дочерних элементов. Это уже поддерживается в Safari , а также в Chrome 105 . Полная таблица поддержки показана ниже:

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

Как работают родительские селекторы в CSS

В CSS, если мы хотим что-то выбрать, мы используем селекторы, которые нисходят на DOM. Например, выбор тега p в теге div выглядит следующим образом:

 div p {
    красный цвет;
}
 

До сих пор мы не могли выбрать тегов div , в которых было тегов p , и это означало, что нам пришлось прибегнуть к Javascript. Основная причина, по которой это не было реализовано в CSS, заключается в том, что это довольно дорогая операция. CSS относительно быстро анализируется, но выбор родительских тегов требует значительно большего объема обработки.

Используя селектор :has , теперь мы можем выбрать элементов div , которые имеют p дочерних элементов, или любую обычную комбинацию селекторов. Например, выбор элемента div с дочерним элементом p теперь выглядит следующим образом:

 /* Цвет элемента div: красный; */
div: имеет (р) {
    красный цвет;
}
 

Это сделает любой div с потомком p красным.

Объединение родительского выбора с другими селекторами

Как и любой другой селектор CSS, мы можем комбинировать его для определенных обстоятельств. Например, если вы хотите выбрать только теги div , которые имеют прямые span дочерние элементы:

 div:has(> span) {
    красный цвет;
}
 

Как следует из словаря :has , он не ограничивается только родительским выбором. Например, ниже мы можем выбрать диапазон , который :has родственный div :

 span:has(+ div) {
    красный цвет;
}
 

Или даже выбор элемента, который имеет дочерний элемент , а не , с помощью селектора :not() . Например, следующее выберет любой div, который делает не есть p дочерний элемент:

 div:not(:has(p)) {
    красный цвет;
}
 

Выбор элементов, содержащих только текст в CSS

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

Хотя это не идеальное решение для простых :пустых элементов с пробелами (поскольку это выберет любой элемент только с текстом и без дополнительных элементов DOM HTML) — это дает нам возможность выбирать элементы DOM только с текстовыми узлами. , что раньше было невозможно. Мы можем добиться этого с помощью следующего кода:

 div:not(:has(*)) {
    фон: зеленый;
}
 

Заключение

С добавлением поддержки селектора :has() в Chrome 105 родительский выбор быстро становится реальностью, которую мы скоро сможем использовать в реальных проектах. На данный момент с поддержкой Safari легко протестировать и посмотреть, как он будет работать в будущем. Это дает дополнительное преимущество, позволяя сократить использование решений Javascript для выбора родительских элементов, что довольно часто встречается во многих приложениях и продуктах.

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

Надеюсь, вам понравилась эта статья. Чтобы узнать больше о CSS, нажмите здесь.

Последнее обновление 1656765087561

Существует ли родительский селектор CSS?

html

1 месяц назад

от Sharqa Hameed

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

», назначенных одному и тому же классу, и требуется стилизовать «div», имеющий тег «

». В таких случаях «

:has() ” используется псевдокласс родительского селектора.

Этот пост будет описывать:

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

Как стилизовать родительский элемент, указав его дочерние элементы?

Сначала создайте файл HTML с двумя элементами «div» следующим образом:

  • Добавьте два «
    » элементы с тем же классом « parent-div ».
  • Первый содержит два элемента «

    ».

  • Второй элемент «
    » содержит «

    » и «

    »:

Привет

мир

Привет

У меня есть тег «h2»

Если требуется стилизовать элемент «

», имеющий элемент «

», то мы можем настроить стиль родительского элемента, удерживая дочерний. Для этой цели мы можем использовать селектор «: has() ».

Из обоих элементов «

» выберите тот, который содержит элемент «

», используя «

.class-name:has(child-name) »:

.parent-div:has (h2) {

background-color: #103e6d;

цвет: морская ракушка;

ширина: 150 пикселей;

высота: 150 пикселей;

радиус границы: 50%;

выравнивание текста: по центру;

}

Здесь мы применили следующие свойства CSS к родительскому элементу:

  • « background-color » используется для указания цвета фона элемента.
  • « color » определяет цвет текста элемента.
  • « ширина » используется для определения ширины элемента.
  • « height » указывает высоту элемента.
  • Свойство « border-radius » используется для установки закругленных углов элемента.
  • « text-align » определяет выравнивание текста.

Вывод

Как выбрать все дочерние элементы?

Чтобы выбрать дочерний элемент с помощью родительского селектора, выполните приведенный пример.

Пример

Выполните следующие действия для создания HTML-страницы:

  • Добавьте элемент div, содержащий два тега «

    » и тег «

    », имеющий класс « child-div ». .
  • Дочерний элемент « div » содержит элемент «

    »:

Привет

мир

я дочерний элемент

Мы можем выбрать дочерние элементы через родительский класс «

». Это не только выберет его прямые элементы « p », но также выберет вложенные элементы « p »:

.parent-div p {

background-color: #7F167F;

семейство шрифтов: скоропись;

размер шрифта: 25 пикселей;

выравнивание текста: по центру;

цвет: бело-дымчатый;

}

Выход

Как выбрать все прямые дочерние элементы?

Чтобы выбрать прямой дочерний элемент родительского элемента div, мы можем использовать символ « > ». Это поможет выбрать все элементы «p», которые являются прямыми дочерними элементами родительского элемента «

». Например, мы применили следующие свойства CSS:

.parent-div>p {

background-color: #7F167F;

семейство шрифтов: скоропись;

размер шрифта: 30 пикселей;

выравнивание текста: по центру;

цвет: бело-дымчатый;

}

« font-family » указывает шрифт выбранного элемента, а « font-size » используется для определения размера шрифта:

Output

7 о родительских селекторах CSS в HTML и CSS.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *