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

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

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

Зачастую лучше вносить изменения в расположение элементов по размерам их контейнера, а не вьюпорта. Для решения этой проблемы родилась концепция элементных запросов. И все же в концепции элементных запросов есть изьяны, и Mat Marquis продемонстрировал их и переформулировал концепцию в контейнерные запросы. К сожалению, и эта концепция до сих пор не идеальна.

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

Flexbox с flex-wrap

Flex-wrap может решить массу проблем, касающихся ответа на размеры контейнера. Например, часто нужно расположить два элемента рядом, если есть место. Если места недостаточно, элементы должны располагаться один над другим. В демо ниже показан этот пример в действии:

Никаких трюков, просто flexbox и flex-wrap, и все работает. С помощью flexbox можно делать много чего. Можно не просто создавать две колонки, но я не стал усложнять демо. Основные моменты техники очень просты:

<div class="container">
  <div class="img">...</div>
  <div class="content">...</div>
</div>

...
.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:

Здесь опять используется техника великолепной четверки, только на этот раз на высоте контейнера, а не ширине.

<div class="outer">
  <div class="inner">
    <div class="item">...</div>
    ...
    <div class="control">...</div>
  </div>
</div>
...
.outer {
  height: 2.25em;
  overflow: hidden;
}

.outer:target {
  height: auto;
}

Высота внешнего контейнера фиксирована и прячет любые заступы, только если это не :target.

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

Внутренний контейнер представляет собой флекс-контейнер со свойством flex-wrap. Когда элементы будут перепрыгивать на строки ниже, высота контейнера будет увеличиваться. Элементы ниже первой сроки прячутся свойством overflow:hidden на контейнере .outer, создавая эффект усечения.

.control {
  height: calc((2.25em - 100%) * -1000);
  max-height: 2.25em;
}

: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. Все это должно настраиваться с помощью элементных/контейнерных запросов в ответ на состояние родительского контейнера, но, увы, в ближайшее время нет никаких признаков, что это воплотится в реальность. Тем не менее, надеюсь, что когда-нибудь что-либо из написанного мной вам пригодится.

Автор: Andy Kirk

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

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

Самые свежие новости IT и веб-разработки на нашем Telegram-канале

Фреймворк Bootstrap - верстаем адаптивно, просто, быстро!

Получите видеокурс по основам Bootstrap

Получить

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree