. . .

Блок нестандартной формы

15 Июль 2019

Одним прекрасным зимнем вечером я со своими друзьями наслаждался игрой Star Wars Battlefront 2. Несмотря на захватывающий игровой процесс я обратил внимание на потрясающий ui этой игры. В особенности меня привлекли модальные окна нестандартной формы (шестиугольные), вот одно из них:

Мне захотелось во чтобы то ни стало повторить это в своей работе и утром на следующий же день я начал подробно изучать этот вопрос. Первый вариант решения этой задачи был посредством псевдоэлементов before и after. Мне не очень хочется описывать всю последовательность действий, поскольку полученный результат меня совершенно не удовлетворил. Я просто выложу этот результат, если вам захочется понять как это работает – всегда можно заглянуть в исходный код.

Почему мне не понравился результат? Во-первых псевдоэлементы находятся на абсолютном позиционировании, приходится сложно и долго по наитию подгонять их, чтобы они оказывались в нужном месте. Во-вторых – видно, что результат получается неаккуратным, границы деформированы. Получив этот результат я продолжил поиски и нашел то, что мне понравилось, а именно свойство clip-path. Как говорит нам https://developer.mozilla.org, свойство clip-path создает ограниченную область, которая определяет какая часть элемента должна быть видимой. Те части, которые находятся внутри области, видимы, в то время как части вне области, скрыты. Мы создадим блок, который становится шестиугольным при наведении курсора на него. Приступим к практическому выполнению поставленной задачи.

Хочу сразу обратить внимание – свойство clip-path по сути обрезает элемент, по этому если мы хотим чтобы у блока была граница – придется ее сымитировать путем создания блока в блоке и выставления отступа нужной ширины.

Итак, HTML-разметка:

<div id="modal-border">
    <div id="modal-div">
        <p>Use the force</p>
    </div>
</div>

Добавляем базовые стили оформления:

div {
   transition: .5s ease;
}
p {
   transition: .5s ease;
}
#modal-border {
   width: 60%;
   margin-top: 30px;
   margin-left: 20%;
   background-color: #000;
   padding: 1px;
}
#modal-div {
   background-color: #fff;
   padding: 100px 0;
}
#modal-div p {
   color: #000;
   font-size: 20px;
   margin: 0;
   text-align: center;
}

На данном этапе блок выглядит следующим образом:

Пришло время для свойства clip-path. Напишу сразу о том, что изначально блок является прямоугольным и может показаться, что в clip-path нужно выставлять четыре точки координат. Однако в конечной версии блока (при hover) у него будет шесть точек. И для того, чтобы свойство transition работало, в начальной также необходимо выставить шесть точек.

#modal-border {
    clip-path: polygon(0 0, 50% 0, 100% 0, 100% 100%, 50% 100%, 0 100%);
}
#modal-div {
    clip-path: polygon(0 0, 50% 0, 100% 0, 100% 100%, 50% 100%, 0 100%);
}
#modal-border:hover {
     clip-path: polygon(0 20%, 50% 0, 100% 20%, 100% 80%, 50% 100%, 0 80%);
}
#modal-border:hover #modal-div {
     clip-path: polygon(0 20%, 50% 0, 100% 20%, 100% 80%, 50% 100%, 0 80%);
}

Посмотрим на получившийся результат:

Если мы хотим, чтобы блок не так сильно обрезался можно, например, в состоянии hover увеличить отступы:

Блок шестиугольной формы готов. Все было бы просто прекрасно, если не одно но - clip-path экспериментальное свойство и поддерживается оно далеко не всеми браузерами. Подробнее с поддержкой можно ознакомиться здесь.

Посмотреть на github