Magic Flip Cards: решение распространенной проблемы с размером

Опубликовано: 2022-03-10
Краткое резюме ↬ В этой статье Дэн Холлидей рассматривает стандартный подход к созданию анимированных флип-карт и представляет улучшенный метод, решающий проблему с размером.

Каковы шансы, что ваш следующий клиент будет использовать слово « интерактивный » при представлении своего проекта? По моему опыту, ответ 100% , поэтому я всегда ищу надежные методы CSS, которые помогут мне реализовать различные функции и эффекты, возникающие при обсуждении этой цели.

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

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

  • Как флип-карты обычно реализуются с использованием абсолютного позиционирования;
  • Проблема размера, которую вводит абсолютное позиционирование; а также
  • Общее решение для автоматического изменения размера наложенного контента.
Еще после прыжка! Продолжить чтение ниже ↓

Создание базовой флип-карты

Благодаря хорошей поддержке трехмерных преобразований современными браузерами создание базовой флип-карты относительно просто. Обычный метод заключается в размещении лицевой и оборотной сторон карты в родительском контейнере и абсолютном размещении обратной стороны таким образом, чтобы она совпадала по размеру с лицевой стороной. Добавьте преобразование по оси X к задней стороне, чтобы оно выглядело перевернутым, добавьте еще одно к самой карте при наведении курсора, и мы в деле.

 .cards { display: grid; } .card { perspective: 40rem; } .card-body { transform-style: preserve-3d; transition: var(--time) transform; .card:hover & { transform: rotateX(-180deg); } } .card-front, .card-back { backface-visibility: hidden; } .card-back { position: absolute; top: 0; right: 0; bottom: 0; left: 0; transform: rotateX(-180deg); } 

Стандартная реализация флип-карты с использованием абсолютного позиционирования (см. Pen «[Magic Flip Cards 1: Стандартная реализация] (https://codepen.io/smashingmag/pen/JjdPJvo)» Дэна Холлидея)

Стандартная реализация флип-карты с использованием абсолютного позиционирования (см. Pen «Magic Flip Cards 1: Стандартная реализация» Дэна Холлидея)

Что может пойти не так?

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

Как стандартная реализация флип-карты терпит неудачу с более длинной задней частью
Вот как стандартная реализация флип-карты терпит неудачу с более длинным содержимым задней части. (Большой превью)

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

Как стандартная реализация флип-карты терпит неудачу с более длинным содержимым задней части (см. Pen «[Magic Flip Cards 2: How Absolute Positioning Fails] (https://codepen.io/smashingmag/pen/QWbLMLz)» Дэна Холлидея)

Как стандартная реализация флип-карты терпит неудачу с более длинным содержимым задней части (см. ручку «Magic Flip Cards 2: How Absolute Positioning Fails» Дэна Холлидея)

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

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

Нестандартное мышление

На самом деле , размеры карточек можно изменять как по содержимому лицевой, так и по оборотной стороне, и это не так сложно, как кажется на первый взгляд. Нам просто нужно быть методичными и настойчивыми!

Ограничение проблемы

Давайте начнем с составления списка требований к нашему макету. Попытка точно записать то, что вы хотите, может показаться рутиной, но это отличный способ выявить ограничения, которые можно упростить для решения проблемы. Скажем:

  • Мы хотим видеть одну или несколько прямоугольных карточек, расположенных в сетке из одного или нескольких столбцов;
  • Мы хотим, чтобы карточки переворачивались при наведении или касании, чтобы открыть второй набор контента на обратной стороне;
  • Мы хотим, чтобы карточки всегда были достаточно большими, чтобы было видно все их лицевое и оборотное содержимое, независимо от длины содержимого или стиля; а также
  • В случае нескольких столбцов в идеале мы хотим, чтобы все карточки были одинакового размера, чтобы строки были хорошо выровнены.

Продумывая эти требования, можно заметить пару вещей, упрощающих задачу:

  • Если карточки будут представлены в сетке, у нас есть ограничение на их ширину — то есть их ширина зависит от окна просмотра или контейнера сетки, а не от их собственного содержимого;
  • Учитывая, что мы знаем ширину карты (по крайней мере, в процентах от ее родителя), мы решили для горизонтального размера, и нам просто нужно увеличить высоту карты, чтобы она соответствовала большей высоте ее передней или задней стороны; а также
  • Если мы сможем это сделать, и каждая карточка имеет свой размер по вертикали, мы можем использовать grid-auto-rows CSS Grid, чтобы сделать все ряды карточек такими же высокими, как самая высокая карточка.

Выяснение карточного фокуса

Итак, как мы сами определяем размер карт? Теперь мы упростили нашу проблему, мы в пределах досягаемости решения.

Забудьте на мгновение об идее размещения контента поверх другого контента и сосредоточьтесь на нашем новом требовании: родитель такого же роста, как и его самый высокий дочерний элемент. Это просто! Используя столбцы, мы можем заставить родителя расширяться до высоты самого высокого дочернего элемента. Затем нам просто нужно использовать небольшую ловкость рук, чтобы выровнять детей:

  1. Установите дочерние элементы той же ширины, что и их родитель.
  2. Разрешить второму дочернему элементу переполняться вправо
  3. Превратите его влево обратно на свое место
 .cards { display: grid; } .card-body { display: flex; } .card-front, .card-back { min-width: 100%; mix-blend-mode: multiply; // Preview both faces } .card-back { transform: translate(-100%, 0); } 

Вертикальный размер с фиксированным горизонтальным переполнением (см. Pen «[Magic Flip Cards 3: Вертикальный размер с фиксированным горизонтальным переполнением] (https://codepen.io/smashingmag/pen/ExjYvjP)» Дэна Холлидея)

Вертикальный размер с помощью фиксированного горизонтального переполнения (см. Pen «Magic Flip Cards 3: Вертикальный размер с помощью фиксированного горизонтального переполнения» Дэна Холлидея)

Если этот подход кажется очевидным, будьте уверены, что я провел много часов, обдумывая некоторые действительно ужасные идеи, прежде чем обдумать их. Сначала я планировал напечатать скрытый дубликат текста на оборотной стороне внутри лицевой стороны, чтобы увеличить карту до нужного размера. И когда я подумал об использовании переполнения столбца, я изначально обрезал правый столбец с помощью overflow:hidden и преобразовывал его только в последний момент, когда начиналось наведение, так как я еще не понял, что могу просто сохранить его преобразованным с самого начала и используйте другой метод, например opacity или backface-visibility , чтобы включать и выключать его по мере необходимости.

Другими словами, очевидные решения — результат упорной работы! Если вы чувствуете, что часами бились головой о стол из-за проблемы макета, важно сделать шаг назад и решить, разумно ли вы тратите время своего клиента: предлагать ли ему изменить дизайн и искать решение в свободное время в качестве учебного упражнения, когда давление спадает. Но когда вы придумываете простые методы, никогда не чувствуйте себя глупо, потому что это заняло много времени . Теперь давайте рассмотрим наше полное решение.

 .cards { display: grid; } .card { perspective: 40rem; } .card-body { display: flex; transform-style: preserve-3d; transition: var(--time) transform; .card:hover & { transform: rotateX(-180deg); } } .card-front, .card-back { backface-visibility: hidden; min-width: 100%; } .card-back { transform: rotateX(-180deg) translate(-100%, 0); } 

Полное решение для волшебных флип-карт (см. Pen «[Magic Flip Cards 4: The Complete Solution] (https://codepen.io/smashingmag/pen/xxGKLZO)» Дэна Холлидея)

Полное решение для волшебных флип-карт (см. Pen «Magic Flip Cards 4: The Complete Solution» Дэна Холлидея)

Есть ли предостережения?

В целом решение работает хорошо, за исключением нескольких незначительных предостережений:

  • Карточки должны присутствовать в макете сетки или в каком-либо другом контексте, где их ширина не зависит от содержимого.
  • Карточкам требуется какая-то обертка содержимого (наша card-body ), ​​чтобы область наведения не менялась во время анимации. Если сама карта анимирована, вы увидите некоторые сбои, поскольку анимация быстро останавливается и перезапускается.
  • Такие стили, как фон и тени, лучше всего размещать непосредственно на передней и задней сторонах карты, так как любые эффекты на самой карте не будут анимированы. Остерегайтесь таких стилей, как тени на корпусе карты, так как они, естественно, будут перевернуты вверх дном.
  • Лицевая и обратная стороны карточек должны иметь свойство box-sizing , установленное на border-box , если у них есть собственные отступы, из-за их требования к min-width , иначе они будут переполнены.
  • Safari по-прежнему требует -webkit-backface-visibility в форме с префиксом поставщика.

Добавление немного польского

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

Во-первых, проверьте, не перекрываются ли карты при переворачивании. Это будет зависеть от того, используете ли вы несколько столбцов, ширины поля столбца, ориентации флипа и значения перспективы карты, но, скорее всего, это произойдет. Вы можете увеличить продолжительность анимации, чтобы видеть вещи более четко. При наведении кажется неестественным, что наведенная карта переворачивается под более поздними соседями, поэтому нам нужно поместить ее сверху, используя z-index . Достаточно просто, но будьте осторожны! Нам нужно дождаться завершения исходящей анимации, прежде чем восстанавливать z-index . Введите transition-delay :

 .card { transition: z-index; transition-delay: var(--time); z-index: 0; &:hover { transition-delay: 0s; z-index: 1; } }

Далее рассмотрите возможность создания активного состояния для карт. Обычно я стараюсь делать такие карточки ссылками на какое-то релевантное место — даже если это не указано дизайнером — поскольку элементы с эффектами наведения, подобные этому, кажутся очень удобными для нажатия, поэтому хорошо предоставить пункт назначения для читателей, которые попытают счастья. Мне нравится короткое тонкое преобразование масштаба, так как оно работает достаточно хорошо, независимо от того, обрезается ли вторая половина анимации при загрузке целевой страницы (хотя мне бы хотелось, чтобы браузеры выполняли анимацию во время полета без ошибок перед навигацией, хотя Я уверен, что реализовать это на практике будет гораздо сложнее, чем кажется).

Это также отличная возможность подумать о том, насколько доступно содержимое рубашек наших карточек. Наша разметка лаконична и упорядочена, поэтому мы рассмотрели средства чтения с экрана и другие варианты использования, которые игнорируют стили, но как насчет пользователей клавиатуры? Если мы собираемся сделать сами карточки якорями, они будут получать фокус, когда пользователи клавиатуры перемещаются по странице. Давайте повторно используем состояние наведения карты в качестве состояния фокуса, и задний контент будет естественным образом отображаться во время просмотра клавиатуры.

 .card { transition: z-index, transform calc(var(--time) / 4); transition-delay: var(--time), 0s; z-index: 0; &:hover { transition-delay: 0s; z-index: 1; } &:active { transform: scale(0.975); } } .card-body { .card:hover &, .card:focus & { transform: rotateX(-180deg); } }

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

 .card-front, .card-back { display: flex; align-items: center; background-color: white; box-shadow: 0 5px 10px black; border-radius: 0.25rem; padding: 1.5rem; }

Подведение итогов

Я надеюсь, что вы найдете эту технику CSS полезной! Почему бы не попробовать некоторые вариации анимации, такие как эффект масштаба или простое плавное затухание? Техника также не ограничивается форм-фактором карт. Его можно использовать везде, где ответственность за вертикальный размер ложится на несколько элементов. Представьте себе веб-сайт журнала с большими фотографиями с наложенными подписями — вы можете использовать его для размещения как изображений с высоким соотношением сторон, так и длинного динамического текста.

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