Pull to refresh

Чего я не знал о CSS

Reading time 6 min
Views 33K
Original author: Dave Smyth
Рисовать сайты я учился по старинке: глядя на исходный код и пытаясь воспроизвести увиденное. Плюс взял странную книгу для невидимых вещей (типа PHP/MySQL) — и вперёд.

Это ещё в 1999 году, когда мы писали <font size="4" color="#000000"> и т. д., а DHTML был модным.

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

Вот некоторые вещи, которых я не знал, но хотел бы узнать раньше.

Block, inline и inline-block


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

Вот вкратце:

  • блочные элементы block расширяются горизонтально, чтобы занять целую строку (например, заголовок). Мы можем применить к ним вертикальные отступы.
  • встроенные элементы inline расширяются горизонтально ровно настолько, чтобы вместить содержимое (например, элементы strong или em). Мы не можем применить к ним вертикальные отступы, и они обычно должны быть помещены внутрь блочного элемента.
  • встроенные блочные элементы inline-block похожи на встроенные элементы, но к ним можно применить вертикальные отступы (что делает их полезными для таких объектов, как кнопки).

В приведённом ниже примере у блочных элементов синий контур, встроенные элементы на оранжевом фоне, а у встроенного блочного элемента красный контур.



Изображения являются встроенными


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

Если в вашем наборе такого нет, предлагаю добавить следующее правило:

img {
    display: block;
}

Это сделает их поведение гораздо более предсказуемым. Возможно, вы также захотите добавить max-width: 100%;, чтобы они не вырывались из своего контейнера.

Как вычисляются высота и ширина


По умолчанию ширина/высота контейнера (box) вычисляется путём сложения:

  • Область контента
  • Область заполнения
  • Область границы

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

Если у нас следующий CSS:

.some-class {
    width: 50%;
    padding: 2em;
    border: 0.1rem;
}

Общая расчётная ширина .some-class будет:

50% + 4em + 0.2 rem

Это происходит из-за свойства под названием box-sizing со значением по умолчанию content-box. Такое значение означает, что свойство width применяется к области контента: все остальное добавляется поверх.

Мы можем изменить это для всех элементов с помощью следующего правила:

* {
    box-sizing: border-box;
}

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

Что происходит с границей и заполнением (padding)? Эти свойства/значения всё ещё применяются, но не влияют на общую ширину элемента: они находятся в пределах определённой области.

Посмотрите код на Codepen, чтобы увидеть это в действии:



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

Отступ и заполнение — не одно и то же


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

  • margin — это пространство между элементами
  • padding — это пространство внутри элемента

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

Поглощение отступов


Это давно раздражает новичков CSS. Рэйчел Эндрю описывает это свойство следующим образом:

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

Если у нас есть два блочных элемента с margin-bottom: 1em на одном элементе и margin-top: 1.5 em на элементе непосредственно под ним, общее пространство между двумя элементами будет равно 1.5 em.

Это видно здесь:



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

Расчёты отступов сразу становятся проще. Это также может изменить наш подход к управлению отступами, и именно на данном этапе может оказаться полезным селектор Lobotomised Owl и тому подобные техники.

Примечание: отступы не поглощаются, когда родительский элемент установлен в display: grid или display: flex.

В браузерах есть таблица стилей по умолчанию


CSS означает «каскадные таблицы стилей». Поэтому неудивительно, что каскад является одним из фундаментальных понятий CSS.

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

Объявленные стили различаются в зависимости от браузера, но именно они являются причиной того, что по умолчанию:

  • У заголовков разные размеры
  • Текст черный
  • Списки маркируются точками
  • У элементов может быть любое свойство display (например, block или inline)

И многие другие вещи.

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

Везде используйте относительные единицы измерения


Использовать пиксели (px) заманчиво, потому что они просты для понимания: объявите размер шрифта 24px, и текст будет 24px. Но это не гарантирует удобства пользователей, особенно которые изменяют размер контента на уровне браузера или увеличивают масштаб.

Я давно начал использовать для определения размера шрифта em (а позже rem). Потребовалось гораздо больше времени, чтобы надёжно освоить em и rem для отступов, полей, интервалы между буквами и границ.

Понимание разницы между em и rem имеет решающее значение, чтобы управлять относительными единицами. Например, мы можем использовать em для запросов @media и вертикальных отступов, но rem для согласованной ширины границ.

Для полного перехода на относительные единицы требуется некоторое усилие для корректировки мышления, но оно того стоит.

Псевдоэлементам ::before и ::after нужен контент


Псевдоэлементы ::before и ::after требуют обязательного указания свойства content, даже если оно остаётся пустым:

.some-class::before {
    content: '';
}

Если оно отсутствует, псевдоэлемент не будет отображаться.

Юнит ch


Единица ch (символ) полезна, в частности, для задания ширины элемента примерно по количеству символов в строке текста.

Почему примерно? Технически, ch не считает реальное количество символов в строке.

Единица ch базируется на ширине символа 0. Об этом писал Эрик Мейер:

«1ch обычно шире среднего символа обычно примерно на 20−30%».

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

Нормальный поток


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

Например, если мы напишем:

<h2>Heading</h2>
<p>Paragraph text.</p>

Мы ожидаем, что <h2>Heading</h2> появится перед или над <p>Paragraph text.</p>. Это нормальный поток.

Если элемент извлечён из нормального потока, он не появится в этом месте. Хороший пример — плавающие и абсолютно позиционированные элементы.

Оформление состояний :focus


Я впервые узнал о псевдоселекторах :hover, :focus и :active в контексте стилизации ссылок. В то время все примеры их использования выглядели примерно так:

a {
    color: black;
}
a:hover,
a:focus,
a:active {
    color: red;
}

Однако лучше иначе оформить состояния :focus.

:focus — это состояние, когда пользователь нажимает или проводит по фокусируемым элементам на странице (например, ссылкам). Когда пользователь нажимает на него [tab], он не знает, где окажется фокус.

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

По всем этим причинам лучше всего стилизовать :focus иначе, чем :hover и :active. Например:

a:hover,
a:active {
    /* styles */
}
a:focus {
    /* styles */
}

:nth-child()


Посмотрите такой код:



Видите, что фоном выделены нечётные строки? Хотя селектор p:nth-child(even) предполагает выделение чётных строк.

Однако селектор :nth-child() подсчитывает все родственные элементы. Указание элемента в селекторе (например, p:nth-child()) не приводит к тому, что селектор начинает отсчёт с первого элемента этого типа.

Вместо этого указание элемента в селекторе означает, что правило будет применяться только к этому типу элемента. Если мы переключим наш пример на нечётные элементы p:nth-child(odd), то увидим, что:

  • h1 не выделяется, хотя это нечётный родственный элемент
  • Отмечены элементы p, соответствующие критериям (параграфы два, четыре, шесть)



Вернёмся к первому примеру. Предположим, мы хотим выделить фоном чётные элементы p. В этом случае нам лучше вообще использовать другой псевдоселектор p:nth-of-type(even)



Это ключевое различие между :nth-child() и :nth-of-type(). Здесь тонкая разница, но она поможет избежать некоторой путаницы.

В завершение


Легко освоить основы CSS, но решающее значение имеет понимание, как и почему всё работает именно так.

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

См. также:

Tags:
Hubs:
+27
Comments 30
Comments Comments 30

Articles