Главная » Статьи » Решение реальных проблем с помощью CSS Grid и Flexbox

Решение реальных проблем с помощью CSS Grid и Flexbox

Решение реальных проблем с помощью CSS Grid и Flexbox

От автора: недавно я столкнулся с адаптивным дизайном, который выглядел сложным в плане измененного порядка элементов и макетов для разных областей просмотра. Этот новый дизайн выглядел сложным, пока мы не рассмотрели его в контексте CSS Grid и FlexBox.

Демо: https://codepen.io/collection/XQdebB/

Проблемой здесь может стать поддержка Internet Explorer 11 и Safari 9+.

После того, как мы рассмотрим сложности дизайна, мы покажем, какой CSS нужен для поддержки современных браузеров, а потом добавим поддержку IE и наконец применим это в работе с Safari 9 + 10.0.

Дизайн

Решение реальных проблем с помощью CSS Grid и Flexbox

Адаптивные макеты для стационарных компьютеров, мобильная версия A и мобильная версия B

Выглядит весьма незатейливо, но нужно сделать несколько примечаний:

Вариант товара меняет порядок

CTA должны соответствовать друг другу

CTA должны находиться ниже цены

CTA не должны перекрывать любую область «текста предложения»

CTA должны находиться ниже изображения (вариант А)

Создание сетки CSS

Разделяем карточки на различные области.

Решение реальных проблем с помощью CSS Grid и Flexbox

Адаптивные макеты с наложенными сетками

Некоторые моменты из спецификаций мы не могли использовать, а именно: grid-column-gap и named grid columns, поскольку их не было в оригинальной структуре и Internet Explorer их не поддерживает.

Mobile Grid Layout

Это достаточно незатейливый макет сетки. Единственное примечание – область d также использует flex и space-between, чтобы разместить кнопки по углам.

.product-card { display: grid; grid-template-rows: repeat(3, min-content); grid-template-columns: 33% 1fr 55px; grid-auto-rows: min-content;
} .grid-area--a { grid-row: 1 / span 2; grid-column: 1;
} .grid-area--b { grid-row: 1; grid-column: 2 / span 2;
} .grid-area--c { grid-row: 2 / span 2; grid-column: 2;
} .grid-area--d { grid-row: 3; grid-column: 1 / span 3; display: flex; flex-basis: 100%; justify-content: space-between;
}

Mobile Grid Layout — Вариант B

Небольшие простые изменения, чтобы адаптировать сетку. Свойство flex direction области d также изменилось, чтобы кнопки теперь выстроились в ряд по вертикали.

.product-card--b .grid-area--a { grid-row: 1 / span 3;
} .product-card--b .grid-area--b { grid-column: 2;
} .product-card--b .grid-area--d { grid-row: 1 / span 3; grid-column: 3; flex-direction: column; justify-content: space-between;
}

Grid Layout для стационарной версии

@media only screen and (min-width: 768px) { .product-card { grid-template-rows: repeat(4, min-content); grid-template-columns: 100%; } .product-card .grid-area { grid-column: 1; } .product-card .grid-area--a { grid-row: 1; } .product-card .grid-area--b { grid-row: 2; } .product-card .grid-area--c { grid-row: 3; } .product-card .grid-area--d { grid-row: 4; } .product-card--b .grid-area--d { flex-direction: row; }
}

Как это выглядит?

Если посмотреть на код сейчас, то наша демо-версия на Codepen замечательно работает в Safari 10.1+, Firefox, Chrome и Opera, но совсем не работает в Internet Explorer или Safari 9 или 10.0.

Internet Explorer

Если вы используете autoprefixer, вам непосредственно придется включить поддержку grid. Это добавит префиксы -ms-:

display: grid; становится display: -ms-grid;

grid-template-rows: repeat(3, min-content); становится -ms-grid-rows: (min-content);

grid-template-columns: 33% 1fr 55px; становится -ms-grid-columns: 33% 1fr 55px;

grid-row: 1 / span 2; становится -ms-grid-row-span: 2; -ms-grid-column: 1;

grid-column: 1; становится -ms-grid-column: 1;

Последний шаг – это на основе медиа-запроса задать / span 1. Все дело в развернутом синтаксисе, если мы забудем задать количество разделов, любой предыдущий -ms-grid-row-span: будет давать нежелательные результаты.

@use autoprefixer { remove: false; grid: true; browsers: "> 1%, firefox 32";
} .product-card { display: grid; grid-template-rows: repeat(3, min-content); grid-template-columns: 33% 1fr 55px; grid-auto-rows: min-content;
} .grid-area--a { grid-row: 1 / span 2; grid-column: 1;
} .grid-area--b { grid-row: 1; grid-column: 2 / span 2;
} .grid-area--c { grid-row: 2 / span 2; grid-column: 2;
} .grid-area--d { grid-row: 3; grid-column: 1 / span 3; display: flex; flex-basis: 100%; justify-content: space-between;
} .product-card--b .grid-area--a { grid-row: 1 / span 3;
} .product-card--b .grid-area--b { grid-column: 2 / span 1; /* explicit span for ie */
} .product-card--b .grid-area--d { grid-row: 1 / span 3; grid-column: 3 / span 1; /* explicit span for ie */ flex-direction: column; justify-content: space-between;
} @media only screen and (min-width: 768px) { .product-card { grid-template-rows: repeat(4, min-content); grid-template-columns: 100%; } .product-card .grid-area { grid-column: 1 / span 1; /* explicit span for ie */ } .product-card .grid-area--a { grid-row: 1 / span 1; /* explicit span for ie */ } .product-card .grid-area--b { grid-row: 2 / span 1; /* explicit span for ie */ } .product-card .grid-area--c { grid-row: 3 / span 1; /* explicit span for ie */ } .product-card .grid-area--d { grid-row: 4 / span 1; /* explicit span for ie */ } .product-card--b .grid-area--d { flex-direction: row; }
}

Демо-версия на CodePen Demo для Internet Explorer

Переходим к Safari 9 + 10.0

Safari ниже 10.1 не поддерживает CSS Grid. Вообще. Это печально и, к сожалению, сетка – это не прогрессивное улучшение, а очень необходимая штука. Но, наверное, не стоит зацикливаться на идеале, давайте попробуем, насколько возможно, улучшить ситуацию.

Safari 9 понимает @supports, но Internet explorer, к сожалению, нет. Это значит, что нам придется найти альтернативу. Так как мы используем PostCSS, мне пришла в голову идея использовать mixin. К сожалению, это сильно раздувает CSS.

@use postcss-mixins;
@define-mixin undoSafariHacks { /* target ie11 only as this doesn't understand `@supports` */ @media (-ms-high-contrast: active), (-ms-high-contrast: none) { @mixin-content; } /* target browsers that support `@supports` */ @supports (display: grid) { @mixin-content; }
}

Используя то же решение Grid Layout, нам нужно добавить floats, widths + margins, чтобы примерно (но не точно) воспроизвести тот же макет в более современных браузерах. Я решил отказаться от идеи воспроизвести мобильную сетку в Safari.

@use postcss-mixins;
@use autoprefixer { remove: false; grid: true; browsers: "> 1%, firefox 32";
} @define-mixin undoSafariHacks { /* target ie11 only as this doesn't understand `@supports` */ @media (-ms-high-contrast: active), (-ms-high-contrast: none) { @mixin-content; } /* target browsers that support `@supports` */ @supports (display: grid) { @mixin-content; }
} .product-card { display: grid; grid-template-rows: repeat(3, min-content); grid-template-columns: 33% 1fr 55px; grid-auto-rows: min-content; align-content: start; /* fix macOS safari 10 */
} .grid-area--a { grid-row: 1 / span 2; grid-column: 1; float: left; /* set for < Safari 10.1 */ display: inline-block; /* set for < Safari 10.1 */ width: 33%; /* set for < Safari 10.1 */
} .grid-area--b { grid-row: 1; grid-column: 2 / span 2; display: inline-block; /* set for < Safari 10.1 */ width: 66%; /* set for < Safari 10.1 */
} .grid-area--c { grid-row: 2 / span 2; grid-column: 2 / span 1; display: inline-block; /* set for < Safari 10.1 */ width: 66%; /* set for < Safari 10.1 */ float: right; /* set for < Safari 10.1 */ margin-left: 33%; /* set for < Safari 10.1 */ } .grid-area--d { grid-row: 3; grid-column: 1 / span 3; display: flex; flex-basis: 100%; justify-content: space-between; width: 100%; /* set for < Safari 10.1 */
} .product-card--b .grid-area--a { grid-row: 1 / span 3;
} .product-card--b .grid-area--b { grid-column: 2;
} .product-card--b .grid-area--d { grid-row: 1 / span 3; grid-column: 3; flex-direction: row; /* set for < Safari 10.1 */ justify-content: space-between;
} @mixin undoSafariHacks { .grid-area--a { width: auto; float: none; display: block; } .grid-area--b { width: auto; display: block; } .grid-area--c { float: none; width: auto; margin-left: 0; } .product-card--b .grid-area--d { flex-direction: column; }
} @media only screen and (min-width: 768px) { .product-card { display: block; } .product-card .grid-area { float: none; /* set for < Safari 10.1 */ width: 100%; /* set for < Safari 10.1 */ margin: 0; /* set for < Safari 10.1 */ } .product-card--b .grid-area--d { flex-direction: row; }
}

Из-за поддержки браузеров, которые не читают CSS Grid, нам пришлось добавить больше кода, но мне кажется, предоставление лучшего макета для большинства пользователей того стоит.

Цена улучшения поддержки браузерами

Вместо от 1.39 Kb мы получили объем 2.76 Kb. Если мы применяем подход к Safari и к Internet Explorer и опускаем -ms- префиксы, то мы снова получим 1.96 Kb.

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

Поддержка Safari < 10.1 заставила нас добавить дополнительный CSS-макет (float, margins и т.д.), поскольку CSS Grid не поддерживается

Дополнительный CSS добавленный для Safari < 10.1 должен быть «ликвидирован» в браузере, который поддерживает @supports

Префиксы Internet Explorer -ms- требуют непосредственного использования / span 1 (хотя оно и выглядит лишним)

Именно вам решать применять ли тот же подход к поддержке IE, что и для Safari < 10.1, чтобы уменьшить раздутие кода.

CSS Grid помогает решать сложные проблемы с макетом и изначально меняет ваше видение этих проблем – создавая более простой код!

Автор: Peter Mouland

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

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