Разрешены ли все правила CSS для всех элементов HTML и могут ли они быть унаследованы?

Учитывая, что определенные правила CSS адаптированы к конкретным элементам HTML (некоторые примеры - object-fit для <img> , <video> и т. Д .; правила stroke , fill и другие SVG для различных элементов SVG) и не совсем имеют смысл при использовании на других элементах:

  1. законно ли применять какое-либо действующее правило CSS к любому элементу HTML?
  2. может ли какое-либо правило быть унаследованным?
  3. каково унаследованное значение, особенно в случаях, когда оно унаследовано от элемента, где использование определенного свойства не имеет смысла?

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

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

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

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


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

.icon {
  stroke: inherit;
  fill: inherit;
}

.button {
  stroke: #FFF;
  fill: #999;
}
<button class="button">
  <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18">
    <g stroke-width="2" transform="translate(1 1)">
      <path d="M14 2L2 14"/>
      <circle cx="8" cy="8" r="8"/>
    </g>
  </svg>
  <span>My button</span>
</button>

Всего 2 ответа


все еще законно применить любое действующее правило CSS к любому элементу HTML?

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

Кроме того, может ли какое-либо правило наследоваться?

Да, но вы должны заметить, что наследование учитывает вычисленное значение, и это может иметь значение:

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

У меня нет тривиального примера, связанного с SVG, но вот еще один:

.box {
  display:inline-block;
  float:left;
  width:200px;
  height:200px;
  border:1px solid red;
}

.box > div {
  display:inherit;
  border:1px solid green;
}
<div class="box">
  <div>text</div>
</div>

Обратите внимание, что внутренний div будет иметь display равное block а не inline-block потому что float заставит вычисленное значение display быть блоком для .box

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

.icon {
  stroke: var(--s);
  fill: var(--f);
}

.button {
  --s: #FFF;
  --f: #999;
}
<button class="button">
  <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18">
    <g stroke-width="2" transform="translate(1 1)">
      <path d="M14 2L2 14"/>
      <circle cx="8" cy="8" r="8"/>
    </g>
  </svg>
  <span>My button</span>
</button>


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

Законно ли применять какое-либо действующее правило CSS к любому элементу HTML?

Да, это так . Это четко указано в спецификации CSS2.1: https://www.w3.org/TR/CSS2/about.html#applies-to (CSS3 является обратно совместимым с модулем расширением CSS2.1, поэтому это все еще применяется). Это говорит:

Считается, что все элементы имеют все свойства, но некоторые свойства не оказывают влияния на некоторые типы элементов. Например, свойство 'clear' влияет только на элементы уровня блока.

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

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

Можно ли наследовать какое-либо правило?

Чтобы ответить на этот вопрос, давайте посмотрим на спецификацию уровня 3 модуля «Значения и единицы измерения CSS»: https://www.w3.org/TR/css3-values/#common-keywords . В нем говорится, что:

Все свойства CSS также принимают значения ключевых слов в масштабе CSS как единственный компонент значения их свойств.

Существует три значения ключевых слов в масштабе CSS: initial , inherit и unset .

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

Как вычисляются унаследованные значения?

Отличное описание каскадирования и наследования - спецификация CSS 3 «Каскадирование и наследование»: https://www.w3.org/TR/css-cascade-3/ . В нем говорится, что:

Унаследованное значение свойства элемента является вычисленным значением свойства родительского элемента элемента.

Основываясь на спецификации, вот моя упрощенная версия процесса определения вычисленного значения для любого свойства любого элемента:

  1. Соберите все объявленные значения для свойства элемента - то есть все соответствующие и действительные объявления CSS, найденные в таблицах стилей разработчика и атрибутах стилей, таблицах стилей пользовательского агента и т. Д.
  2. Определите каскадное значение - выигрышное значение всех объявленных значений (именно здесь правила имеют приоритет, а одно выходит на первое место).
  3. Если каскадного значения нет, используйте наследуемое значение, если свойство наследуется.
  4. Если свойство не наследуется (см. Этот вопрос для получения списка свойств, которые наследуются по умолчанию: какие свойства CSS наследуются? ), Используйте начальное значение . Каждое свойство имеет начальное значение в соответствии со спецификацией (например, начальный font-size medium ; стоит отметить, что это не абсолютное значение, как 16px !).
  5. На этом этапе свойству будет присвоено некоторое значение, но оно может быть относительным, то есть зависеть от некоторых других свойств CSS (например, процентное значение зависит от некоторого абсолютного значения, такого как абсолютные измерения родителя). На этом шаге значение будет разрешено настолько, насколько это возможно, чтобы оно было однозначным и готовым к наследованию .

    Важно отметить, что точно так же, как спецификация определила начальное значение для каждого свойства, она также определяет, как получить вычисленное значение . Например, MDN указал это вычисленное значение для размера шрифта:

как указано, но с относительными длинами, преобразованными в абсолютные длины

Таким образом, medium остается medium , но 1.2em становится, скажем, 19.2px (если размер шрифта родителя равен 16px ).

Важный бит

Те же спецификации каскадирования и наследования указывают, что:

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

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

Что все это значит для моего примера кнопки SVG:

  1. Мне определенно разрешено устанавливать stroke и fill <button> . Он будет игнорировать это свойство при рендеринге, но при необходимости передаст его своим дочерним элементам.
  2. Дочерний SVG будет наследовать эти свойства по умолчанию (мне даже не нужно явно указывать это).
  3. Вычисленные значения для stroke и fill не имеют никаких оговорок, поэтому я могу ожидать, что правильный цвет будет унаследован (и это так!).