CSS: выберите элемент и все его потомки

Чтобы выбрать элемент и все его дочерние элементы:

.media, .media * {color: #f00;}

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

3 ответа

Решение

С XPath у вас есть descendant-or-self ось

Но в CSS такого селектора нет.

В 2023 году недавние дополнения к синтаксису CSS и доступные псевдоклассы откроют несколько интересных альтернативных способов решения этой проблемы (хотя они все еще не так идеальны, как действительно нативный комбинатор «я» или «потомок »).

Давайте рассмотрим гипотетический.proseкласс, который идентифицирует авторский контент сайта, который может быть доставлен, например,<article>или<section>блоки с вложенной структурой или, например, элементы, которые непосредственно содержат текст.

Имея только строгие комбинаторы потомков и традиционный синтаксис CSS, такие элементы, как<p>и<blockquote>требуют добавления (потенциально несемантической) оболочки, такой как<div>элемент.

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

      h1.prose, .prose h1 {...}
h2.prose, .prose h2 {...}
h3.prose, .prose h3 {...}
h4.prose, .prose h4 {...}
h5.prose, .prose h5 {...}
h6.prose, .prose h6 {...}

p.prose, .prose p {...}

blockquote.prose, .prose blockquote {...}

/* And so forth... */

Используя последние разработки CSS, вышеизложенное можно переписать следующим образом:

      .prose, .prose * {
    
    &:is(h1) {...}
    &:is(h2) {...}
    &:is(h3) {...}
    &:is(h4) {...}
    &:is(h5) {...}
    &:is(h6) {...}
    
    &:is(p) {...}

    &:is(blockquote) {...}

    /* Alternatively, the :where() pseudo-class can also be used,
       which differs in how specificity is calculated. */
}

Очевидно,&:is(...)часть по-прежнему является шаблонной, но повторение значительно сокращено, что можно считать улучшением.

Предостережение: по состоянию на май 2023 года поддержка браузером встроенной вложенности CSS все еще находится в стадии разработки (см. https://caniuse.com/css-nesting ), и код CSS, использующий эту возможность, должен быть преобразован в невложенный. синтаксис (с использованием, например, плагина postcss-nesting ). :is()псевдокласс пользуется более широкой поддержкой (см. https://caniuse.com/?search=is).

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

      :root {
    --ctx-media: ;
    --ctx-not-media: initial;
}

.media {
    --ctx-media: initial;
    --ctx-not-media: ;
}

* {
    color: var(--ctx-media, #f00) 
           var(--ctx-not-media, inherit);
}

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

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

      * {
    /* WRONG!!! Will resolve to `color: ;` when --ctx-media is defined */
    color: var(--ctx-media, #f00);
}

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

      :root {
    --ctx-media: ;
    --ctx-not-media: initial;
}

.media {
    --ctx-media: initial;
    --ctx-not-media: ;
}

@layer media {
    * {
        color: var(--ctx-media, #f00) 
               var(--ctx-not-media, revert-layer);
    }
}

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

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

Как слои CSS, так и пользовательские свойства широко поддерживаются браузерами.

Другие вопросы по тегам