Невидимые части CSS

Spread the love
  • 2
    Поделились

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

Оригинальная статья: Mike — The invisible parts of CSS

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

Возможно, вы этого не осознали, но внешний вид создаваемый CSS часто являются косвенным следствием манипулирования скрытыми свойствами. Некоторые свойства CSS, такие как background-color, имеют прямую и очевидную связь с тем, что вы видите. В то время как другие, такие как display, остаются для многих из нас неоднозначными, потому что результаты кажутся сильно зависимыми от контекста.

Я сомневаюсь, что многие разработчики могли бы описать простым языком, что на самом деле делает установка display: block. В лучшем случае у вас, вероятно, есть интуитивное понимание того, как работают это свойство. Это нормально, у вас может быть довольно хорошее умение работать с CSS без понимания основополагающих принципов.

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

Базовые функции CSS сложны и намеренно абстрагированы, но мы не можем не знать о них. Такие понятия, как Box Model (Блоковая модель), Cascade (каскадность) и Specificity могут быть знакомы многим из нас, хотя их часто неправильно понимают. Более точные знания того как это работает может помочь нам лучше писать CSS.

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

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

Обзор процесса рендеринга

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

Первым шагом запускается анализ документа HTML. Благодаря ему браузер строит «дерево документов» (document tree). Древовидная структура — это способ представления информации с очевидной иерархией, такой как HTML. Элементы в дереве могут быть описаны в терминах, похожих на семейное древо, таких как потомки (descendants), родители (parents), дети (children) и братья и сестры (siblings).

Возможно, вы слышали термин DOM. Он означает объектную модель документа (Document Object Model). Это представление древовидной структуры документа и используется для хранения и управления информацией о содержимом веб-документа.

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

Во время этого процесса определяется окончательные значения свойств CSS. После расчета эти значения могут отличаться от того, что написано в ваших таблицах стилей. Например, ключевым словам, таким как auto и относительным единицам (em, vh и т.п.), назначаются реальные значения и применяются унаследованные значения. Эти вычисленные значения хранятся в дереве, аналогично элементам в DOM, что неудивительно называется объектной моделью CSS (CSS Object Model) или CSSOM.

После этого начинается процесс рендеринга страницы. Первым шагом в этом процессе является расчет Box Model. Это важный шаг для определения размера и расстояния между элементами, хотя тут не определяется их окончательное положение.

Менее известным, чем Box Model, является процесс, называемый моделью визуального форматирования (Visual Formatting Model). Этот процесс определяет расположение элементов на странице. Он охватывает некоторые концепции, с которыми вы, возможно, уже знакомы, такие как схемы позиционирования (positioning schemes), контексты форматирования (formatting contexts), режимы отображения (formatting contexts) и контексты стекирования (stacking contexts).

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

В вышеприведенных параграфах может быть несколько терминов, с которыми вы еще не знакомы. Если это так, то самое важное — это понять, что Cascade, Box Model и Visual Formatting Model являются ключевыми этапами интерпретации, обработки и визуализации HTML и CSS. Я пропустил много деталей при описании каждого из них, поэтому сейчас мы рассмотрим эти три шага более внимательно.

Cascade

Cascade, вероятно, является одной из самых неправильно понятых особенностей CSS. Это сложность относится к процессу объединения различных таблиц стилей и разрешения конфликтов между селекторами CSS.

Cascade учитывает importance, origin, specificity (специфичность) и порядок объявлений элементов, чтобы определить, какие правила стиля использовать.

Большинство веб-сайтов имеют несколько таблиц стилей. Обычно стили добавляются с тегом link, который ссылается на файл CSS, или с тегом style в теле HTML. Так же любая даже самая простая страница имеет стили по умолчанию, предоставленные браузером. Эта таблица стилей по умолчанию иногда называется таблицей стилей агента пользователя (user-agent stylesheet).

Во время процесса Cascade интерпретируются таблицы стилей в следующем порядке:

  1. объявление с !important
  2. Авторские таблицы стилей
  3. Браузерные таблицы стилей по умолчанию

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

Specificity

Specificity — это вес, данный селекторам. Распространенная ошибка — думать об этом как о простом числе. На самом деле это 4 отдельных числа или 4 категории взвешивания.

Чтобы рассчитать специфичность, посчитайте следующие номера:

  1. ID,
  2. классы, атрибуты и псевдо-классы,
  3. элементы and псевдо-элементы

Для примера: #nav .selected:hover > a::before будет 1, 2, 2.

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

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

Да! Я знаю, я сказал 4 категории. Встроенные стили имеют более высокую специфичность, чем идентификаторы. Хотя технически они являются первой категорией в вычислениях специфичности, расчет обычно не заканчивается конкурирующими встроенными стилями, поэтому легче просто помнить, что встроенные стили всегда выигрывают специфичность.

Важное примечание: объявления !important не учитываются при вычислениях специфичности, так как имеют больший приоритет, чем обычные объявления в процессе Cascade.

Наследование

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

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

Вы, вероятно, знакомы с тем фактом, что свойства шрифта при применении к body или другому элементу контейнера также наследуются каждым элементом внутри этого контейнера. Это называется наследование.

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

Примечание. Некоторые свойства, такие как border-color, имеют значение по умолчанию currentcolor. Это означает, что они будут использовать значение, установленное в свойстве color. Это значение по умолчанию не то же самое, что наследование. Хотя само свойство цвета часто наследуется, поэтому я склонен думать об этом как о фактическом типе наследования.

The Box Model

Понимание Box Model необходимо для понимания работы с макетами и позиционированием. Это одна из самых фундаментальных концепций в CSS.

Box model используется для расчета ширины и высоты элементов. Это этап расчета, который используется не только для определения окончательного расположения и расположения элементов.

Каждый элемент в HTML представляет собой прямоугольное поле. Каждое поле имеет четыре области определяющие margin, borders , padding и области содержимого элемента (content areas).

По умолчанию, когда вы устанавливаете ширину элемента (width), это устанавливает ширину только области содержимого. Когда вы добавляете отступы (padding), границы (border) или поля (margin) к элементу, они добавляются в дополнение к ширине. На практике это означает, что два элемента шириной 50% не будут помещаться рядом, если будут добавлены отступы (padding), поля (margin) или границы (borders).

shows the content-width within the box model

Это довольно просто, верно? Так почему же это часто источник путаницы? Ну, вы, возможно, сталкивались с несколькими ситуациями, когда вещи, кажутся одни образом в ведут себя немного другим…

Fill Area

Когда вы устанавливаете фон элемента, он заполняет не только область содержимого, но также области отступов (padding) и границ (border).

shows the fill area within the box model

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

Примечание. Изменение свойства box-sizing может изменить это поведение.

Width Auto

Другой источник потенциальной путаницы — как работает width: auto. Ширина auto является настройкой по умолчанию для большинства элементов HTML, а для таких блочных элементов, как div и p, auto рассчитает ширину таким образом, чтобы margin, border, padding и содержимое вмещались в доступное пространство.

В этой ситуации может показаться, что при добавлении padding и margins в области содержимого внутрь, но на самом деле ширина пересчитывается, чтобы гарантировать, что все подходит. Для сравнения, при установке ширины 100% область содержимого будет заполнять доступное пространство независимо от margin, padding и borders.

Box-sizing

Свойство box-sizing изменяет способ работы блочной модели. Если для параметра box-size задано значение border-box, и border будет уменьшать внутреннюю ширину области содержимого, а не увеличивать общую ширину элемента. Это означает, что ширина элемента теперь равна его визуальной ширине.

shows how box-sizing:border-box works

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

Исчезающий margin

Это может быть очень сложным для объяснения, когда margin неожиданно схлопываются, и вы не понимаете, что происходит. Margin иногда могут сжиматься, когда два или более смежных вертикальных margin соприкасаются, и они не разделены padding или border. Исчезающий margin также может возникнуть, если margin дочернего элемента распространяется на margin его родительского элемента и они не разделены padding.

Margin не исчезнет, если элементы абсолютно позиционированы, floated или имеют другой контекст форматирования (formatting context), а также в некоторых других менее вероятных ситуациях.

Если вы запутались, это нормально. Правила, когда margin будут и не будут разрушаться, сложны. Главное, что вам нужно знать, это то, что когда элементы не имеют padding или borders, вертикальные margin могут удаляться.

Если вам нужно больше подробностей, у CSS Tricks есть замечательное объяснение исчезающему margin (collapsing margins).

Модель визуального форматирования

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

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

Это сложный шаг, и на данный момент его очень сложно объяснить для подведения итогов. Если вы не во всем разобрались, это нормально. Понимание того, как мы манипулируем схемами позиционирования (positioning schemes) и контекстами форматирования (formatting contexts) через свойства CSS, уже является хорошим началом. Если вы сможете понять как взаимодействуют различные части этой модели, вы начнете разбираться во всем этом лучше, чем большинство. Ну или по крайней мере, вы должны знать, что такие понятия существуют.

Типы display

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

Это связано с тем, что свойство display определяет «box type» элемента. Это скрытое свойство состоит из внутреннего типа отображения и внешнего типа отображения, которые вместе помогают определить способ визуализации элемента.

Внешний тип отображения обычно разрешается либо «block», либо «inline» и в значительной степени соответствует тому, что вы ожидаете от этих свойств display в CSS. Технически говоря, внешний тип отображения диктует, как элемент участвует в родительском контексте форматирования (formatting context).

Внутренний тип отображения определяет, какой контекст форматирования (formatting context) будет генерировать этот элемент. Это повлияет на расположение дочерних элементов.

Подумайте, как работает контейнер Flexbox. Его внешний тип — block, а внутренний — flex. Его дочерние элементы также могут иметь внешний тип block, но на их расположение влияет контекст форматирования контейнера Flexbox.

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

Контексты форматирования

Контекст форматирования (formatting context) — все о макете (layout). Это правила, которые определяют расположение элементов внутри контейнера и то, как они взаимодействуют друг с другом.

Некоторые контексты форматирования могут быть установлены непосредственно на контейнерах, например, с использованием display значений flex, grid или table. Другие типы, такие как block и inline, создаются в соответствии с требованиями браузера.

Схемы позиционирования

Блок на странице может быть разложен по одной из трех схем позиционирования (positioning schemes). Это Normal flow, Floats и Absolute positioning. Вы, вероятно, знакомы с floats и absolute, потому что мы часто взаимодействуем с ними непосредственно при написании CSS. Normal flow — это просто имя для схемы позиционирования по умолчанию, когда элемент не floated или не positioned.

Normal flow

Normal Flow описывает схему позиционирования по умолчанию, и «in-flow» описывает элементы, которые соответствуют этому. Можно рассматривать порядок расположение элементов, согласно их расположению в соответствии с порядком в исходном коде с учетом контекста форматирования (formatting context).

Floats

Float — это свойство CSS, которое заставляет элемент вырываться из нормального потока (Normal Flow) и смещаться влево или вправо, насколько это возможно, до тех пор, пока он не коснется края содержащего его блока или другого плавающего элемента. Когда это произойдет, текст и встроенные элементы будут обтекать float элементы.

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

Именно такое поведение позволяет нескольким строкам текста, заголовкам и другим элементам плавно обтекать floated контент. Но иногда это проблематично. Исправления и установление нового контекста форматирования блока приведут к тому, что контейнер очистит свои floated дочерние элементы. Этот метод позволил использовать floated элементы для макета, который долгое время был краеугольным камнем технологий веб-разработки.

Хотя это по-прежнему важно знать, но это поведение постепенно заменяется новыми технологиями компоновки, такими как Flexbox и Grid.

Absolute positioning

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

Контейнер с относительным позиционированием позволяет вам контролировать смещение элементов-потомков, используя абсолютное позиционирование.

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

Свойства CSS top, bottom, left и right используются для вычисления «box offsets». Эти свойства не являются двумерными смещениями, но позволяют позиционировать каждое ребро относительно поля содержимого его контейнера.

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

Stacking contexts

Контекст стека определяет порядок, в котором вещи отображаются на странице. Вы можете думать о стековом контексте как о слоях. Слои внизу стека закрашиваются последующими, и элементы выше стека появляются сверху.

Размещение z-index на элементе, который позиционируется абсолютно или относительно, является наиболее распространенным способом создания нового стекового контекста. Но существует множество других способов формирования контекста стека, включая установку непрозрачности, преобразований, фильтров или использование свойства will-change.

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

Установка z-index не имеет никакого эффекта, если контекст стека не установлен. Чем больше z-index, тем выше в стеке размещен слой.

Одна из самых запутанных частей в стеке — то, что новый контекст стека может быть установлен внутри существующего. Это означает, что вы можете иметь слои внутри других слоев. И а этой ситуации не всегда больший z-index означает высшее расположение в стеке.

Заключение

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

Я надеюсь, что мне удалось кое-что прояснить или дать общее представление о вовлеченных процессах. Было непросто объяснить все это простым языком, не жертвуя при этом точностью. Я надеюсь, что у меня это получилось.

Была ли вам полезна эта статья?
[7 / 3.9]

Spread the love
  • 2
    Поделились

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