3D-эффект наведения на кнопку
Я пытаюсь воспроизвести этот эффект с помощью чистого CSS:
Пока я пробовал делать:
.parent {
height: 90vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.hoverable-element {
border: 0.1rem solid #000;
background: #fff;
padding: 1rem 2rem;
transform: translate(0, 0);
box-shadow: 0 0 0 #000;
transition:
box-shadow 200ms ease-out,
transform 200ms ease-out;
}
.hoverable-element:hover {
transform: translate(-0.5rem, -0.5rem);
box-shadow:
0.1rem 0.1rem 0 #000,
0.2rem 0.2rem 0 #000,
0.3rem 0.3rem 0 #000,
0.4rem 0.4rem 0 #000,
0.5rem 0.5rem 0 #000;
}
<div class="parent">
<button class="hoverable-element">Hoverable Button</button>
</div>
Но этот метод повторяет много ненужного кода, а также неправильно выполняет то, что я задумал. Я хочу, чтобы «тень» кнопки .hoverable-element (эффект выдавливания при наведении) была окаймлена белым фоном (как показано на изображении). Кроме этого, я не знаю, с чего начать
Свободный перевод вопроса 3D-like hover effect on button от участника @Fredrik Strøm-Larsen.
Ответы (2 шт):
Вот идея с псевдоэлементом и преобразованием skew:
.parent {
height: 90vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.hoverable-element {
border: 1px solid #000;
background: #fff;
padding: 1rem 2rem;
position: relative;
transition: transform 0.5s;
}
.hoverable-element::before,
.hoverable-element::after {
content: "";
position: absolute;
border: inherit;
transition: inherit;
}
.hoverable-element::before {
height: 1rem;
top: 100%;
left: -1px;
right: -1px;
transform-origin: top left;
transform: skewX(45deg) scaleY(var(--s, 0));
}
.hoverable-element::after {
width: 1rem;
left: 100%;
top: -1px;
bottom: 0;
border-bottom:none;
transform-origin: bottom left;
transform: skewY(45deg) scaleX(var(--s, 0));
}
.hoverable-element:hover {
transform: translate(-0.5rem, -0.5rem);
--s: 1;
}
<div class="parent">
<button class="hoverable-element">Hoverable Button</button>
</div>
Свободный перевод ответа от участника @Temani Afif.
Как мне кажется, логичнее было бы анимировать кнопку немного иначе. Добавить анимацию не только при наведении, но и при нажатии. Пример:
button,
button:hover,
button:active {
outline: none;
cursor: pointer;
}
.parent {
height: 90vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.hoverable-element {
width: 160px;
height: 50px;
border: 1px solid #000;
background: #fff;
padding: 1rem 2rem;
position: relative;
transition: transform 0.3s;
}
.hoverable-element::before,
.hoverable-element::after {
content: "";
position: absolute;
border: inherit;
transition: inherit;
}
.hoverable-element::before {
height: 1rem;
top: 100%;
left: -1px;
right: -1px;
transform-origin: top left;
transform: skewX(45deg) scaleY(0.5);
}
.hoverable-element::after {
width: 1rem;
left: 100%;
top: -1px;
bottom: 0;
border-bottom: none;
transform-origin: bottom left;
transform: skewY(45deg) scaleX(0.5);
}
.hoverable-element:hover {
transform: translate(-0.5rem, -0.5rem) scaleX(1);
}
.hoverable-element:hover::before {
transform: skewX(45deg) scaleY(1);
}
.hoverable-element:hover::after {
transform: skewY(45deg) scaleX(1);
}
.hoverable-element:active {
transform: translate(0.5rem, 0.5rem) scaleX(1);
}
.hoverable-element:active::before {
transform: skewX(45deg) scaleY(0);
}
.hoverable-element:active::after {
transform: skewY(45deg) scaleX(0);
}
.hoverable-element>span::before {
content: 'Кнопка';
}
.hoverable-element:active span::before {
content: 'Кнопка нажата';
}
<div class="parent">
<button class="hoverable-element"><span></span></button>
</div>
Кроме этого, в соседнем ответе кнопка немного сдвигается с места при наведении. Думаю, что это небольшая ошибка. По логике такого быть не должно. Поэтому при наведении и при нажатии необходимо корректировать transform: translate.
upd 1 по комментарию:
button,
button:hover,
button:active {
outline: none;
cursor: pointer;
}
.parent {
height: 90vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.hoverable-element {
width: 160px;
height: 50px;
border: 1px solid #000;
background: #fff;
padding: 1rem 2rem;
position: relative;
transition: transform 0.3s;
}
.hoverable-element::before,
.hoverable-element::after {
content: "";
position: absolute;
border: inherit;
transition: inherit;
}
.hoverable-element::before {
height: 1rem;
top: 100%;
left: -1px;
right: -1px;
transform-origin: top left;
transform: skewX(45deg) scaleY(0.5);
}
.hoverable-element::after {
width: 1rem;
left: 100%;
top: -1px;
bottom: 0;
border-bottom: none;
transform-origin: bottom left;
transform: skewY(45deg) scaleX(0.5);
}
.hoverable-element:hover {
transform: translate(-0.5rem, -0.5rem) scaleX(1);
}
.hoverable-element:hover::before {
transform: skewX(45deg) scaleY(1);
}
.hoverable-element:hover::after {
transform: skewY(45deg) scaleX(1);
}
.hoverable-element:active {
transform: translate(0.5rem, 0.5rem) scaleX(1);
box-shadow: none;
animation-fill-mode: both;
animation: 0.07s forwards shadow 0.2s;
}
@keyframes shadow {
from {
box-shadow: none;
}
to {
box-shadow: inset -1px -2px 7px 0px rgba(0, 0, 0, 0.7);
}
}
.hoverable-element:active::before {
transform: skewX(45deg) scaleY(0);
}
.hoverable-element:active::after {
transform: skewY(45deg) scaleX(0);
}
.hoverable-element>span::before {
content: 'Кнопка';
}
.hoverable-element:active span::before {
content: 'Кнопка нажата';
}
<div class="parent">
<button class="hoverable-element"><span></span></button>
</div>
upd 2 по комментарию:
button,
button:hover,
button:active {
outline: none;
cursor: pointer;
}
.parent {
height: 90vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.hoverable-element {
width: 160px;
height: 50px;
border: 1px solid #000;
background: #fff;
padding: 1rem 2rem;
position: relative;
transition: transform 0.3s;
}
.hoverable-element::before,
.hoverable-element::after {
content: "";
position: absolute;
border: inherit;
transition: inherit;
}
.hoverable-element::before {
height: 1rem;
top: 100%;
left: -1px;
right: -1px;
transform-origin: top left;
transform: skewX(45deg) scaleY(0.5);
}
.hoverable-element::after {
width: 1rem;
left: 100%;
top: -1px;
bottom: 0;
border-bottom: none;
transform-origin: bottom left;
transform: skewY(45deg) scaleX(0.5);
}
.hoverable-element:hover {
transform: translate(-0.5rem, -0.5rem) scaleX(1);
}
.hoverable-element:hover::before {
transform: skewX(45deg) scaleY(1);
}
.hoverable-element:hover::after {
transform: skewY(45deg) scaleX(1);
}
.hoverable-element:active {
transform: translate(0.5rem, 0.5rem) scaleX(1);
box-shadow: none;
animation-fill-mode: both;
animation: 0.05s forwards shadow 0.1s;
}
@keyframes shadow {
from {
box-shadow: none;
}
to {
box-shadow: inset 2px 2px 5px 0px rgba(0, 0, 0, 0.5);
}
}
.hoverable-element:active::before {
transform: skewX(45deg) scaleY(0);
}
.hoverable-element:active::after {
transform: skewY(45deg) scaleX(0);
}
.hoverable-element>span::before {
content: 'Кнопка';
}
.hoverable-element:active span::before {
content: 'Кнопка нажата';
}
<div class="parent">
<button class="hoverable-element"><span></span></button>
</div>
