<Zhenya>
← Блог

Шпаргалка по CSS

И продвинутые CSS штуки

Единицы измерения

Помимо стандартных px и % существует 1001 способ задать размер элементам.

Зависящие от размера шрифта

em - зависит от font-size дочернего элемента

rem - зависит от font-size элемента html

Относительно экрана (viewport-а)

Появились в первую очередь для мобилок

  • vw - viewport width, % от ширины окна браузера.
  • vh - viewport height, % от высоты окна браузера
  • vmin, vmax - для мобилок, % от меньшей/большей размерности вьюпорта вне зависимости от ориентации

Проблемы - не учитываются размеры элементов браузера, например адресная строка в safari или клавиатура

Чтобы решить эти проблемы - придумали новый костыль модификаторы:

  • svh - small viewport height, представляет высоту области просмотра, когда пользовательский интерфейс адресной строки еще не уменьшил свой размер. svh отвечает за то содержимое страницы, которое вы будете видеть, когда интерфейс адресной строки растянут до максимума.
  • lvh - large viewport height, представляет высоту области просмотра после того, как пользовательский интерфейс адресной строки уменьшил свой размер. lvh отвечает за то содержимое страницы, когда пользовательский интерфейс сжат до минимума.
  • dvh - dynamic viewport height - использует любое из значений svh или lvh в зависимости от того, уменьшен ли интерфейс адресной строки. dvh просчитывает переходные состояния между максимальным и минимальным размером UI в браузере.
  • svw, lvw, dvw - такая же история для ширины области просмотра
  • svmin, lvmin, dvmin - аналог vmin, vmax

Однако классическую проблему со скроллбаром новые единицы так и не решили - 100svw = 100dvw = 100lvw = 100vw

Решение проблемы со скроллбаром
html,
body {
scrollbar-gutter: stable;
}
/* 100vw не вызовет появление горизонтального скролла */
.full-width {
width: 100vw;
}

либо

body {
margin: 0;
container-type: inline-size;
}
.full-width {
width: 100vw; /* fallback for older browsers */
width: 100cqw; /* 100cqw учитывет сколлбар */
}

Зависящие от размера блока

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

  • cqw: 1% of a query container's width
  • cqh: 1% of a query container's height
  • cqi: 1% of a query container's inline size
  • cqb: 1% of a query container's block size
  • cqmin: The smaller value of either cqi or cqb
  • cqmax: The larger value of either cqi or cqb

Чтобы использовать эти единицы измерения, нужно задать container-type у родительского контейнера:

Объяснение container-type
.container {
container-type: inline-size;
container-name: card;
}
.container-child {
width: 100cqw; /* всегда будет того же размера, что и my-container */
}

cqw всегда зависит от ширины контейнера, даже если есть вложенность.

<div className="container">
<div className="container-inner">
<div className="container-child">
Hi
</div>
</div>
</div>
.container {
width: 400px;
height: 400px;
background: blueviolet;
container-type: inline-size;
container-name: card;
}
.container-inner {
width: 300px;
}
.container-child {
width: 100cqw; /* 400px, а не 300px */
height: 40px;
background: red;
}

Можно использовать в медиазапросах:

@container (min-width: 400px) { /* Если ширина ближайшего контейнера больше 400px */
.card h2 {
font-size: 2em;
}
}
@container card (min-width: 400px) { /* Если ширина контейнера с именем card больше 400px */
.card h2 {
font-size: 2em;
}
}

Зависящие от соотношения сторон

aspect-ratio - соотношение ширины к высоте, например 1 / 1 - квадрат, а 16 / 9 - прямоугольник

Можно использовать в медиазапросах, для этого есть min-aspect-ratio, max-aspect-ratio

@media screen and (min-aspect-ratio: 16/10) {
/* something for wide screens */
}

Селекторы

/* По id */
#foo {}
/* По классу */
.bar {}
/* По наличию аттрибута */
.input[type]
/* По значению аттрибута */
.input[type="submit"]
/* Потомок с классом .bar внетри элемента с классом .foo */
.foo .bar {}
/* Элемент с классом .foo И классом .bar */
.foo.bar {}
/* Непосредственная вложенность - .bar может быть только на первом уровне вложенности */
.foo > .bar {}
/* Стили для .bar, если он расположен сразу после .foo (сосед) */
.foo + .bar {}
/* Стили для любого .bar, если он расположен после .foo (но не обязательно сосед)*/
.foo ~ .bar {}

Псевдоклассы

Псевдокласс - ключевое слово, добавленное к селектору для уточнения его состояния.

selector:pseudo-class {
property: value;
}

Самые полезные:

  • :hover - при наведении

  • :focus - при фокусе (tab)

  • :focus-within - при фокусе этого элемента или его детей

  • :active - при активации, например при зажатии ЛКМ

  • :checked - для выбранных <input type="radio">, <input type="checkbox"> или <option> внутри <select>

  • :disabled - для кнопок

  • :empty - когда у элемент пуст (нет children), можно применить .element:empty { display: none } вместо условного рендеринга

  • :first-child - первый ребенок своего родителя

  • :first-of-type - первый ребенок такого типа, например первый div

  • :last-child - последний ребенок своего родителя

  • :last-of-type - последний ребенок такого типа, например последний div

  • :nth-child() - какой-то конкетный ребенок (1-й, второй, третий, четный, нечетный)

  • :nth-of-type() - какой-то конкетный элемент такого типа

  • :only-child - единственный ребенок

  • :only-of-type - единственный элемент такого типа

  • :valid, :optional, :required - для валидации форм

  • :visited - для посещенных ссылок, рудимент если честно

  • :is() - позволяет проще писать сложный CSS

.card h1,
.card h2,
.card h3 {
color: black;
}
.card :is(h1, h2, h3) {
color: black;
}
a:hover,
a:focus {
color: purple;
}
a:is(:hover, :focus) {
color: purple;
}
  • :where() похож на :is, но позволяет убить специфичность, идеально для reset

  • :has() - позволяет проверить наличие у родителя наличие какого-то селектора внутри и выбрать именно родителя

/* Если в форме есть невалидный инпут - покрась submit кнопку в красный */
.my-form:has(input:invalid) button[type="submit"]{
background: red;
}
/* */
html:has(.modal.open) {
background: red;
}

Псевдоэлементы

Псевдоэлементы не существуют в HTML разметке, они создаются только с помощью CSS, их нельзя создать, выбрать(querySelector-ом) и менять при помощи JS.

  • ::after - добавить какой-то контент после элемента (создать псевдоэлемент, который является последним потомком)
  • ::before - до (создать псевдоэлемент, который будет первым потомком)
  • ::first-letter - стилизовать первую букву
  • ::first-line - стилизовать первую линию