Очередность в CSS (когда порядок в CSS имеет значение)

Очередность в CSS (когда порядок в CSS имеет значение)

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

В одном файле стилей

К примеру, у нас есть HTML код:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div class="module module-foo module-bar">
    Module
  </div>
</body>
</html>

Порядок атрибутов в HTML не играет никакой роли, а вот порядок в стилях очень важен. Разберем свойство background:

/* 
  Все селекторы совпадают
  И обладают одинаковой специфичностью
*/					

.module {
  background: #ccc;
  padding: 20px;
  max-width: 400px;
  margin: 20px auto;
}

.module-foo {
  background: orange;
}

/* Побеждают ПОСЛЕДНИЕ объявления */
.module-bar {
  background: lightblue; /* Я выиграл! */

  /* Остальные стили */
}

Специально запутанный пример

Порядок не ограничивается только одним объявлением стилей. Еще более важен порядок объявления стилей в документе.
Обратите внимание на документ ниже с тремя разными объявлениями стилей. Назовем их кусочками. Эти кусочки — это <link rel=»stylesheet»>, блок style и @import.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>

  <!-- #1 -->
  <link rel="stylesheet" href="1.css">

  <!-- #2 -->
  <style>
    .module-baz {
      background-color: pink;
    }
  </style>

</head>
<body>
  <div class="module module-foo module-bar module-baz">
    Module
  </div>

  <!-- #3 -->
  <style>
    @import "2.css";
    /*
      Contains
      .module-bar { background: #f06d06; }
    */
  </style>

</body>
</html>

Я пометил наши кусочки как #1, #2 и #3. Все они содержат селекторы с одинаковой специфичностью. Кусочек #3 объявлен последним, а значит, он побеждает.

Асинхронно загружаемые стили CSS тоже соблюдают очередность

Скажем, вы загружаете CSS при помощи специального загрузчика типа loadCSS. Что будет, если загрузить четвертый CSS файл с точно такими же настройками, как в запутанном примере выше?

Загрузчик loadCSS по умолчанию вставляет стили в конец тега head. То есть этот файл станет #3, а блок style перед закрывающим тегом body превратится в #4. Кусочек #4 в таком случае выиграет.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <link rel="stylesheet" href="1.css">

  <script src="loadCSS.js"></script>
  <script>
    loadCSS("2.css");
  </script>

  <!-- 2.css будет вставлен в этом месте -->
</head>
<body>
  <div class="module module-foo module-bar module-late">
    Module
  </div>
</body>
</html>

На самом деле, нельзя вставлять теги link и style в тег body (хоть это и работает). Вероятность того, что загруженные при помощи loadCSS стили не сработают, крайне мала. Можно указать ID, чтобы контролировать порядок CSS:

<script id="loadcss">
  // файл CSS будет загружен прямо перед тегом script с этим кодом
  loadCSS("path/to/mystylesheet.css", document.getElementById("loadcss"));
</script>

Странный критический CSS

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

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    /* #1 
       Критический CSS код */
  </style>
  <script>
    /* #2
       Загружаем оставшийся CSS 
    */
  </script>
</head>
<body>
  <div class="module module-foo module-bar">
    Module
  </div>
</body>
</html>

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

Необходимо точно решить, какие стили перенести в критические, а какие нет, чтобы избежать странных мерцаний при смене стилей.

Странные расширения

Расширения в препроцессорах ведут себя странно. К примеру, вы хотите по-разному стилизовать элемент:

<div class="module module-variation">Module</div>

Код препроцессора будет таким (супер упрощенный код чисто для демо):

%variation {
  background: orange;
}

.module {
  background: #ccc;
  padding: 20px;
  max-width: 400px;
  margin: 20px auto;
}

.module-variation {
  @extend %variation;
}

Вы можете подумать: «хорошо, .module-variation объявлен ПОСЛЕДНИМ, он выиграет, фон будет оранжевым». Это не так, так как расширение перемещает селектор в то место, где расширение было объявлено. В нашем случае это место находится перед стилями, которыми мы пытались переписать фон. Скомпилированный CSS код:

.module-variation {
  background: orange;
}

.module {
  background: #ccc;
  padding: 20px;
  max-width: 400px;
  margin: 20px auto;
}

Свойство background примет значение #ccc, а не то, что мы хотим. Наверное, проще такую проблему решить при помощи специфичности, а не очередности стилей. Родные расширения, когда будут введены, будут менее запутанными.

Довольно запутанный механизм

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

Автор: Chris Coyier

Источник: https://css-tricks.com/

Редакция: Команда webformyself.

Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Получить

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

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

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

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree