Как добавить резервный Flexbox вариант для CSS Grid

От автора: в предыдущей статье я рассказал о том, как с помощью CSS Grid создать календарь. Сегодня я хочу поделиться тем, как создать для CSS Grid резервный Flexbox вариант для того же календаря.

Как обеспечить поддержку

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

.selector { property: fallback-value; property: actual-value;
}

Второй метод: написать резервный код. Переопределить резервный код в запросе функций CSS Feature Queries (@supports). Сбросить свойства внутри @supports, если нужно.

.selector { property: fallback-value;
} @supports (display: grid) { property: actual-value;
}

Третий метод: написать все в @supports.

@supports not (display: grid) { .selector { property: fallback-value; }
} @supports (display: grid) { .selector { property: actual-value; }
}

Эти три метода перечислены в порядке убывания сложности. (Если вам нужно переопределить код, это сложнее). Это означает, что написать все в @supports является самым простым из трех способов. Как вы решите поддерживать свой проект, зависит от поддержки браузера для:

Функций

Резервных функций

Запросов функций

Проверка поддержки

Лучшее место, чтобы проверить поддержку — caniuse. Здесь я могу видеть, что поддержка для CSS Grid вполне достойная. Браузеры, о которых я должен беспокоиться:

Opera Mini: глобальное использование 1,42%

Браузеры Android с 2.1 по 4.4.4: 0,67% мирового использования

Браузер Blackberry: глобальное использование 0,02% (не стоит беспокоиться об этом).

Как добавить резервный Flexbox вариант для CSS Grid

Поддержка для резервного варианта (Flexbox) тоже хороша.

Но у нас есть проблема: запасной вариант Flexbox не будет работать в Android с 2.1 по 4.3 (они не поддерживают переносы). Глобальное использование для Android 2.1 — 4.3 составляет 0.37%. Здесь я должен решить:

Стоит ли предоставлять запасной вариант Flexbox для Opera Mini (1,42%), Android 4.4.4 (0,3%) и Blackberry (0,02%)?

Стоит ли менять запасной вариант с Flexbox на более старую функцию для поддержки Android 2.1 — 4.3 (еще 0.37%)?

Как добавить резервный Flexbox вариант для CSS Grid

Давайте предположим, что для этого проекта я решил, что запасной вариант Flexbox достаточен. Я не собираюсь беспокоиться об Android 2.1 — 4.3. Далее я хочу проверить, поддерживают ли браузеры CSS Feature Queries. Здесь я вижу:

Opera Mini поддерживает запросы функций

Android 4.4.4 поддерживает запросы функций

Браузер Blackberry не поддерживает запросы функций

IE 11 не поддерживает запросы функций

Решите, как написать резервный код

Ранее я упоминал, что есть три способа написания резервного кода для CSS:

Написать резервный код. Переопределить резервный код.

Написать резервный код. Переопределить резервный код в @supports.

Написать все в @supports.

Если я напишу все внутри @supports, я могу предоставить поддержку для:

Opera Mini (1,43%)

Android 4.4.4 (0,3%)

Но я теряю поддержку для:

IE 11 (2,3%)

Blackberry (0,02%)

Я не хочу отказываться от 2,3% пользователей IE, что означает, что метод 3 (написать все в @supports) не подходит.
Если я использую метод 2 (написать резервный код, переопределить резервный код в @supports), я могу обеспечить поддержку для:

IE 11 (2,3%)

Opera Mini (1,43%)

Android 4.4.4 (0,3%)

Blackberry браузер (0,02%)

Это все, что мне нужно. Вот почему я собираюсь выбрать метод 2.

Примечание. Если вы хотите переопределить код, вы можете использовать в качестве отправной точки демо из моей предыдущей статьи.

Отключение кода Grid

Во-первых, мы размещаем код CSS Grid в @supports (как мы уже было сказано выше).

@supports (display: grid) { .day-of-week, .date-grid { display: grid; grid-template-columns: repeat(7, 1fr); } .date-grid button:first-child { grid-column: 6; }
}

Мы можем отключить код CSS Grid, установив для display недопустимое значение (не grid). Это отключит весь блок кода. (Спасибо Рэйчел Эндрю за этот изящный трюк. Думаю, я научился у нее).

@supports (display: gridx) { /*...*/
}

Как добавить резервный Flexbox вариант для CSS Grid

Написание кода Flexbox

Нам нужно построить ту же сетку из семи столбцов с помощью Flexbox. Первое, что нам нужно сделать, это признать, что Flexbox и Grid работают по-разному. Мы не сможем получить идеальную копию, но мы можем создать что-то близкое. Первое, мы установим для display — flex.

.day-of-week,
.date-grid { display: flex;
}

Как добавить резервный Flexbox вариант для CSS Grid

Нам нужно, чтобы кнопки в .date-grid переносились, поэтому мы установили для flex-wrap — wrap.

.date-grid { flex-wrap: wrap;
}

Как добавить резервный Flexbox вариант для CSS Grid

Нам нужно скопировать сетку из семи столбцов. Простой способ сделать это — рассчитать ширину сетки в соответствии с шириной каждой кнопки. Здесь я уже установил для каждой кнопки 4.5ch. Это означает, что ширина сетки должна быть 7 x 4.5ch.

(Мы можем использовать CSS Calc, чтобы выполнить расчеты.)

.day-of-week,
.date-grid { max-width: calc(4.5ch * 7);
}

Как добавить резервный Flexbox вариант для CSS Grid

Нам нужно, чтобы элементы .day-of-week распределились на всю доступную ширину. Простой способ сделать это — установить для justify-content — space-between.

.day-of-week { justify-content: space-between;
}

Как добавить резервный Flexbox вариант для CSS Grid

Здесь мы видим, что элементы .day-of-week выходят за пределы сетки. Это происходит потому, что мы позволяем Flexbox рассчитывать flex-basis. Если мы хотим, чтобы каждый элемент .day-of-week имел одинаковую ширину, нам нужно установить flex-basis самим.

В этом случае самый простой способ — установить ширину одного элемента сетки flex-basis (или 4.5ch). Примечание: я задал font-size для каждого элемента .day-of-week — 0.7em (для визуальной эстетики). Мы должны учитывать это изменение.

.day-of-week > * { flex-basis: calc(4.5ch / 0.7);
}

Как добавить резервный Flexbox вариант для CSS Grid

Наконец, нам нужно сместить 1 февраля на пятницу. (Пять столбцов). Поскольку столбец имеет 4.5ch, мы просто смещаем его на 4.5ch x 5. (Опять же, мы можем использовать CSS Calc).

.date-grid button:first-child { margin-left: calc(4.5ch * 5)
}

Как добавить резервный Flexbox вариант для CSS Grid

Исправление версии CSS Grid

Мы можем повторно активировать код CSS Grid и внести любые необходимые изменения.

@supports(display: grid) { /* ... */
}

Как добавить резервный Flexbox вариант для CSS Grid

Здесь мы видим, что некоторые значения уходят далеко вправо. Это происходит потому, что мы добавили margin-left для первого элемента сетки. Нам нужно сбросить добавленное поле.

@supports(display: grid) { /* ... */ .date-grid button:first-child { grid-column: 6; margin-left: 0; }
}

Как добавить резервный Flexbox вариант для CSS Grid

Еще одна вещь: мы можем удалить max-width, потому что нам это не нужно в коде CSS. (Даже если это не влияет на код CSS, все же лучше это удалить. Всегда лучше иметь меньше свойств).

@supports(display: grid) { .day-of-week, .date-grid { display: grid; grid-template-columns: repeat(7, 1fr); max-width: initial; } /* ... */
}

Вот визуальная разница между версиями Flexbox и CSS Grid. Не так уж плохо!

Как добавить резервный Flexbox вариант для CSS Grid

Одна забавная вещь

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

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

Как добавить резервный Flexbox вариант для CSS Grid

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

Как добавить резервный Flexbox вариант для CSS Grid

Поскольку поддержка логических свойств CSS не так уж и велика, мы должны предоставить запасной вариант. (Лучший способ — использовать метод 1: написать резервный код; переопределить резервный код).

.date-grid button:first-child { margin-left: calc(4.5ch * 5); margin-inline-start: calc(4.5ch * 5);
} @supports(display: grid) { /* ... */ .date-grid button:first-child { grid-column: 6; margin-left: 0; margin-inline-start: 0; }
}

Вот и все! Вот Codepen окончательного кода:

Источник: https://zellwk.com

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