Расположение элементов по кругу с помощью CSS

Если вы любите экспериментировать или немного работали с веб-дизайном, то наверняка вы уже пытались расставить элементы на окружности. Если вы не CSS хакер, то скорей всего вы устанавливали элементам класс или идентификатор, а потом с помощью left и right расставляли по кругу.

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

А что если это можно сделать на чистом CSS? Ana Tudor предложила такое решение на StackOverflow. Вместо того чтобы использовать базовое позиционирование, она опирается на CSS трансформации. Это великолепно. Ну что же, давайте пойдем дальше.

Текущее решение

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

[…] После того как вы решили на каких углах у вас будут ссылки с изображениями, вы добавляете класс deg{desired_angle} (например deg0 или deg45 ну или любой другой). И для каждого такого класса вы применяете CSS трансформацию, вот так:

… где соответственно заменяете {desired_angle} на 0 или 45, и так далее…

Первый rotate поворачивает элемент вокруг своих осей, translate перемещает элемент вокруг повернутой оси X, а второй rotate возвращает элемент в исходное положение. Вот демо пример того как это работает.

Так как Ana добавляет классы для HTML элементов, это не позволяет на быстро добавлять или удалять элементы. Это обязывает нас добавлять соответствующие классы для новых элементов, изменять имя и вдобавок изменять CSS уже существующих элементов чтобы равномерно их расположить. Даа, это облом.

Sass в помощь

Я был уверен, что с помощью Sass я смогу сделать что-то крутое очень легко. И на самом деле, я сделал Mixin для обработки позиционирования всех элементов автоматически. Плюс:

  • Вы можете определить количество элементов на окружности;
  • Вы можете использовать любые элементы, которые только захотите, даже различные между собой (li, div, span, a, img и другие);
  • Просто размещает элементы. Не больше, не меньше. Всякие модный штучки на ваше усмотрение;
  • Включает в себя небольшой reset, для того чтобы вы могли использовать неупорядоченные списки;
  • Заботится о префиксах, благодаря Compass;
  • Делает откат, для старых браузеров;
  • Прост в использовании;

Аргументы которые вы можете передать в Mixin:

  • $nb-items (integer) — количество элементов, которые вы хотите расположить по кругу;
  • $circle-size (length) — размер вашего круга;
  • $item-size (length) — размер элемента;
  • $class-for-IE (string|false) (по желанию) — класс, которые используется в качестве запасного варианта для псевдо-элементов;

Таким образом, использовать его очень просто:

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

Как это работает?

А работает это все очень просто. Он делит число которое вы передаете в параметре на 360 (градусов), чтобы вычислить угол между двумя элементами. После этого запускается цикл @for использующий псевдо-элементы (:nth-of-type()), для того чтобы назначить каждого элементу соответствующие трансформации.

CSS на выходе (с 8 элементами, и размером контейнера в 24em):

А как насчет старых браузеров?

Основная проблема в том при использовании такой техники размещения элементов, является то что IE-8 не поддерживает псевдо-элементы и CSS трансформации.

Первое, что приходит в голову это плагин Selectivizr, которые включает поддержку псевдо-элементов в старых браузерах, ну или немного JavaScript кода, чтобы добавить пронумерованный класс каждому элементу. Вот пример того, как я это сделал (с jQuery):

В таком случае, Sass нужно немного изменить:

Первая проблема решена. Не старайтесь бороться с самой большой проблемой, IE-8 не поддерживает CSS трансформации. Будем надеяться, что мы сможем сделать запасной вариант, который используя margin’ы все таки сделает все круто для этих браузеров.

В принципе, вместо двойного переворота и перемещения элементов, мы можем применить левый и верхний margin (местами отрицательный), чтобы расположить их по кругу. Ребята, пристегните ремни. Расчеты просто безумные:

Да, это определенно не самый простой способ сделать это, так как он содержит какие-то сложные расчеты (поблагодарим Ana за формулы), но он работает словно магия.

Теперь нужно понять, как использовать все эти штуки для IE-8, чтобы не загрязнить современные браузеры? Я обнаружил, что самое простое решение, это добавление флага к Mixin’у, если он включен значит мы должны поддерживать старые браузеры IE и использовать классы и margin’ы. В противном случае мы используем CSS трансформации и псевдо-элементы. Рассмотрим следующую структуру:

Вуаля! Теперь у нас есть Mixin который работает корректно даже в IE-7 (возможно даже и в IE-6), благодаря небольшому количеству JavaScript’а. Разве не приятно?

Заключение

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

See the Pen Items on circle by Hugo Giraudel (@HugoGiraudel) on CodePen.

Комментарии

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