Адаптивні CSS шаблони медіа запитів

32

Від автора: незважаючи на назву, ця стаття не присвячена яким-небудь спроб позбутися медіа запитів. Медіа запити неймовірно корисні, я використовую їх скрізь. Однак вони не вирішують всі наші проблеми з адаптивним дизайном.

Часто краще вносити зміни в розташування елементів за розмірами контейнера, а не вьюпорта. Для вирішення цієї проблеми народилася концепція елементних запитів. І все ж у концепції елементних запитів є вилучили, і Mat Marquis продемонстрував їх і переформулював концепцію контейнерні запити. На жаль, і ця концепція досі не ідеальна.

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

Flexbox з flex-wrap

Flex-wrap може вирішити масу проблем, що стосуються відповіді на розміри контейнера. Наприклад, часто потрібно розташувати два елемента поруч, якщо є місце. Якщо місця недостатньо, елементи повинні розташовуватися один над іншим. У демо нижче показаний цей приклад в дії:

Жодних трюків, просто flexbox і flex-wrap, і все працює. З допомогою flexbox можна робити багато чого. Можна не просто створювати дві колонки, але я не став ускладнювати демо. Основні моменти техніки дуже прості:


.container {
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.container .content,
.container .img {
flex: 1 0 12em;
/* Замініть 12em на свій брейкпоинт. */
}

Для правильної роботи важливо розуміти, що з себе представляють властивості flex-grow, flex-shrink і flex-basis. У Zoe Gillenwater є дуже корисний рада з flexbox, допомагає зрозуміти зв’язок між цими властивостями.

Техніка чудової четвірки

Перемикання ширини по брейкпоинтам з допомогою властивостей width, min-width, max-width і calc (або «техніка чудової четвірки») було дітищем Rémi Parmentier. Спочатку створена для адаптивних електронних листів, ця техніка може легко використовуватися і на звичайних веб-сторінках. Як показав Thierry, ця техніка відкрила нові можливості у створенні самоадаптирующихся модулів. Наприклад:

{
min-width: 50%;
width: calc((25em — 100%) * 1000);
max-width: 100%;
/* Змініть 25em на свій брейкпоинт. */
}

Техніка працює, оскільки якщо width задана у відсотках, відсотки рахуються від ширини контейнера елемента. Функція calc порівнює це значення з бажаним брейкпоинтом і генерує дуже велике позитивне число (якщо ширина менше брейкпоинта) або дуже негативне число (якщо ширина більше брейкпоинта), або нуль, якщо ширина збігається. Велике позитивне число записується у max-width, велике негативне або нуль записуються в min-width.

У наведеному вище прикладі ми поставили брейкпоинт 25em. Якщо шрифт дорівнює 16px, це значення переводиться в 400px. Якщо контейнер 400px або вище (тобто дорівнює або більше брейкпоинта), ширина дорівнює нулю або великому негативному числу:

(400 — 400 = 0) * 1000 = 0 or (400 — 401 = -1) * 1000 = -1000

З такими значеннями у нас спрацьовує min-width, і результуюча ширина елемента в наведеному вище прикладі буде дорівнювати 50%. Однак якщо контейнер 399px і нижче (тобто менше брейкпоинта), ширина дорівнює великому позитивному числу:

(400 — 399 = 1) * 1000 = 1000

У цьому випадку спрацьовує max-width, і результуюча ширина дорівнює 100%. Малюнок нижче повинен допомогти візуалізувати цей процес:

Адаптивные CSS шаблоны без медиа запросов

Чотири демо нижче по-різному використовують цю техніку для перемикання ширини елемента у відповідь на ширину контейнера.

Зображення з обтіканням – ширина повна/часткова ширина

У цьому демо я використовував техніку чудової четвірки разом зі властивість float для перемикання зображення з повною на половину ширини залежно від ширини контейнера:

Як і в прикладі з flexbox вище, ця техніка дозволяє елементам перемикатися між одноколоночным видом при маленькій ширині і видом з обтіканням при достатній ширині.

Зображення з обтіканням – видимий/прихований

Ця техніка адаптована до попередньої. Тут інвертований результат обчислень, і видалено властивість min-width, що створює перемикач вкл/викл. Зручно для приховування декоративних елементів в маленьких контейнерах, адже вони можуть займати цінне простір:

І для ясності:

{
/* Видалено властивість min-width, нам потрібно, щоб ширина була дорівнює нулю, а негативна ширина також вважалася нулем */
/* Інвертований множник: */
width: calc((25em — 100%) * -1000);
max-width: 100%;
/* Змініть 25em на свій брейкпоинт. */
}

Текст і зображення – накладення/стек

Аналогічним чином з попередніми техніками я використовував додатковий div, щоб помістити текст поверх зображення. Якщо зображення занадто маленьке, і текст його закриває, він поміщається під зображення. Ця частина трохи складна, спробую пояснити.

.pull {
/* Вміщуємо текст поверх зображення: */
margin-bottom: -10em;
}

Негативний margin має контент поверх зображення. Однак коли ширина контейнера перетинає брейкпоинт, нам необхідно відключати цю властивість. Але у нас немає властивостей min/max-margin, тому ми не можемо використовувати техніку чудової четвірки.

Як би те ні було, якщо padding заданий у відсотках, то це відсотки від ширини контейнера, і padding-top і –bottom вплинуть на висоту елемента. Знаючи це, ми можемо використовувати calc для створення padding-bottom, яка на основі ширини контейнера буде перемикатися між нулем і дуже великим значенням:

padding-bottom: calc((30em — 100%) * 1000);

Безпосередньо до .pull ми це застосувати не можемо, у нас немає властивостей min/max-padding, щоб обмежити ці значення. Вихід – перемикач помістити padding’а на псевдоэлемент для примусової зміни висоти, а також використовувати max-height на .pull і обмежувати висоту на значення від’ємного margin’а. Так ми ефективно компенсуємо цей margin.

.pull {
/* Вміщуємо текст поверх зображення: */
margin-bottom: -10em;
/* Не даємо контейнера бути більше: */
max-height: 10em;
/* Ховаємо все, що виходить за краї: */
overflow: hidden;
}
.pull::before {
content: «»;
display: block;
padding-bottom: calc((30em — 100%) * 1000);
/* Змініть 30em на свій брейкпоинт */
}

Ефект градієнта перекриття реалізований з допомогою перемикача вкл/викл, як описано раніше:

.image::after {
content: «»;
display: block;
position: absolute;
left: 0;
top: 0;
/* Gradient to make the text more legible: */
background-image: linear-gradient(to bottom, rgba(0,20,30,0) 0%,rgba(0,20,30,0) 50%,rgba(0,20,30,1) 100%);
/* Extra .5% to prevent bleed due to rounding issues: */
height: 100.5%;
/* Toggle gradient overlay at the same breakpoint as the ‘pull’: */
width: calc((30em — 100%) * -1000);
/* Change 30em to your breakpoint */
max-width: 100%;
}

Усічення списку

Остання розроблена мною техніка була натхненна шаблоном Priority Plus з сайту CSS tricks. Техніка досить проста і не вимагає JS:

Тут знову використовується техніка чудової четвірки, тільки на цей раз на висоті контейнера, а не ширині.


.outer {
height: 2.25 em;
overflow: hidden;
}
.outer:target {
height: auto;
}

Висота зовнішнього контейнера фіксована і ховає будь-заступи, тільки якщо це не :target.

.inner {
display: flex;
flex-wrap: wrap;
}

Внутрішній контейнер являє собою флекс-контейнер з властивістю flex-wrap. Коли елементи будуть перестрибувати на рядок нижче, висота контейнера буде збільшуватися. Елементи нижче першої терміни ховаються властивість overflow:hidden на контейнері .outer, створюючи ефект скорочення.

.control {
height: calc((2.25 em — 100%) * -1000);
max-height: 2.25 em;
}
:target .control—open {
display: none;
}
:target .control—close {
display: block;
}

Елементи more/less видно тільки, якщо висота контейнера перевищує брейкпоинт (який дорівнює висоті головних посилань). Стан :target визначає, який елемент буде видимим.

Розумне вирівнювання тексту в CSS

Дуже зручно вирівнювати текст по центру або по лівому краю в залежності від доступного простору в контейнері по порівняння з довжиною тексту. Техніка за авторством Vijay Sharma робить це дуже легко.

Бонус: хак flex-grow 9999

В нашу колекцію відмінно підходить трюк Joren Van Hee – хак flex-grow 9999.

Дивіться, ніяких медіа запитів від Vasilis van Gemert

Виступ Vasilis van Gemert дивіться, ніяких медіа запитів додало мені імпульс на вивчення адаптивного дизайну без медіа запитів, що, в свою чергу, призвело до написання цієї статті. Варто подивитися на його виступ, воно включає в себе парочку інших ідей, які, хоч і корисні, не зовсім вписуються в тему того, що я тут представив.

Висновок

Багато чого неможливо виконати без елементних/контейнерних запитів. Список дуже довгий, це кольори, розмір шрифту, висоту рядка, рамки і тіні, margin і padding. Все це повинно налаштовуватися з допомогою елементних/контейнерних запитів у відповідь на стан батьківського контейнера, але, на жаль, найближчим часом немає ніяких ознак, що це втілиться в реальність. Тим не менше, сподіваюся, що коли-небудь що-небудь з написаного мною стане вам у пригоді.