Кнопка со стрелкой вправо - переход

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

body {
  background: gray;
background-image: linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),
linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),
linear-gradient(30deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),
linear-gradient(150deg, #445 12%, transparent 12.5%, transparent 87%, #445 87.5%, #445),
linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a), 
linear-gradient(60deg, #99a 25%, transparent 25.5%, transparent 75%, #99a 75%, #99a);
background-size:80px 140px;
background-position: 0 0, 0 0, 40px 70px, 40px 70px, 0 0, 40px 70px;
  font-family: sans-serif;
}
.more-skewed {
  display: inline-block;
  position: relative;
  color: white;
  text-decoration: none;
  border: solid 2px white;
  border-right: none;
  box-sizing: border-box;
  padding: 15px 40px;
  letter-spacing: 3px;
  transition: all 1s ease-out;
}

.more-skewed:before {
  content: '';
  position: absolute;
  left: 100%;
  margin-left: -10px;
  top: -2px;
  bottom: 50%;
  border-right: solid 2px white;
  transform: skewX(25deg);
  width: 15px;
  background: inherit;
}

.more-skewed:after {
  content: '';
  position: absolute;
  left: 100%;
  margin-left: -10px;
  bottom: -2px;
  top: 50%;
  border-right: solid 2px white;
  transform: skewX(-25deg);
  width: 15px;
  background: inherit;
}

.more-skewed:hover {
  color: black;
 background: white;
}
<a class="more-skewed" href="#">MORE</a>

Возможно ли это решить? JSfiddle - https://jsfiddle.net/k9jhuc34/
(Кнопка изначально прозрачна и находится над фоном изображения.)

3 ответа

Решение

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

Использование Skew Transform:

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

body {
  background: gray;
  font-family: sans-serif;
}
.more-skewed {
  display: inline-block;
  position: relative;
  color: white;
  text-decoration: none;
  border-left: solid 2px white;
  box-sizing: border-box;
  padding: 15px 40px;
  letter-spacing: 3px;
  transition: all 1s ease-out;
  overflow: hidden;
}
.more-skewed:before {
  content: '';
  position: absolute;
  left: -2px;
  top: 0px;
  bottom: 50%;
  border-right: solid 2px white;
  border-top: solid 2px white;
  transform: skewX(25deg);
  transform-origin: right bottom;
  width: 100%;
  transition: all 1s ease-out;
  z-index: -1;
}
.more-skewed:after {
  content: '';
  position: absolute;
  left: -2px;
  bottom: 0px;
  top: 50%;
  border-right: solid 2px white;
  border-bottom: solid 2px white;
  transform: skewX(-25deg);
  transform-origin: right top;
  width: 100%;
  transition: all 1s ease-out;
  z-index: -1;
}
.more-skewed:hover {
  color: black;
}
.more-skewed:hover:before,
.more-skewed:hover:after {
  background: white;
}
<a class="more-skewed" href="#">MORE</a>


Использование поворота с перспективой:

Другое решение может заключаться в использовании преобразований поворота с добавлением некоторой перспективы. Установив соответствующее значение для transform-origin мы можем заставить его производить трапецию, которая может быть помещена в соответствующие позиции для создания стрелки. Здесь область наведения / удара остается внутри фигуры, но этот подход полезен, только если текст небольшой и статичный. Если текст становится длиннее, наклон с правой стороны фигуры становится более плавным, а не крутым (конечно, мы можем изменить преобразования, чтобы он выглядел лучше, но это не очень полезно, если мы должны продолжать изменять это часто).

.more-skewed {
  display: inline-block;
  position: relative;
  color: white;
  text-decoration: none;
  border: solid 2px white;
  border-right: none;
  box-sizing: border-box;
  padding: 16px 40px;
  letter-spacing: 3px;
  margin: 10px;
}
.more-skewed:before,
.more-skewed:after {
  position: absolute;
  content: '';
  height: 50%;
  width: 100%;
  left: 0;
  border-right: 3px solid white;
  transition: all 1s ease-out;
}
.more-skewed:before {
  top: -2px;
  border-top: 2px solid white;
  transform-origin: left top;
  transform: perspective(100px) rotateX(30deg);
}
.more-skewed:after {
  bottom: -2px;
  border-bottom: 2px solid white;
  transform-origin: left bottom;
  transform: perspective(100px) rotateX(-30deg);
}
.more-skewed:hover {
  color: black;
}
.more-skewed:hover:before,
.more-skewed:hover:after {
  background: white;
}
.more-skewed span {
  position: relative;
  z-index: 1;
}
body {
  background: gray;
  font-family: sans-serif;
}
<a class="more-skewed" href="#">
  <span>MORE</span>
</a>
<br/>
<a class="more-skewed" href="#">
  <span>MORE LONGER TEXT</span>
</a>

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


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

body {
  background: gray;
  font-family: sans-serif;
}
.more-skewed {
  display: inline-block;
  position: relative;
  color: white;
  text-decoration: none;
  border: solid 2px white;
  border-right: none;
  box-sizing: border-box;
  padding: 15px 40px;
  letter-spacing: 3px;
  transition: all 1s linear;
  background: linear-gradient(245deg, transparent 9px, white 10px), linear-gradient(295deg, transparent 9px, white 10px);
  background-size: 0% 50%;
  background-position: top right, bottom right;
  background-repeat: no-repeat;
}
.more-skewed:before {
  content: '';
  position: absolute;
  left: 100%;
  margin-left: -7px;
  top: -2px;
  bottom: 50%;
  transform: skewX(25deg);
  width: 15px;
  background: linear-gradient(white, white);
  background-size: 3px 100%;
  background-repeat: no-repeat;
  background-position: top right;
  transition: all 1s 1s linear;
}
.more-skewed:after {
  content: '';
  position: absolute;
  left: 100%;
  margin-left: -7px;
  bottom: -2px;
  top: 50%;
  transform: skewX(-25deg);
  width: 15px;
  background: linear-gradient(white, white);
  background-size: 3px 100%;
  background-repeat: no-repeat;
  background-position: top right;
  transition: all 1s 1s linear;
}
.more-skewed:hover {
  color: black;
  background-size: 100% 50%;
  transition: all 1s 1s linear;
}
.more-skewed:hover:before,
.more-skewed:hover:after {
  color: black;
  background-size: 100% 100%;
  transition: all 1s linear;
}
<a class="more-skewed" href="#">MORE</a>

Пожалуйста, проверьте ниже код стрелки с transitionНадеюсь, это поможет.

Спасибо

HTML

<a class="arrow_box">
MORE
</a>

CSS

body {
  background: gray;
  font-family: sans-serif;
}
.arrow_box {
    position: relative;
    background: gray;
    border: 2px solid #ffffff;
  display:inline-block;
  padding: 15px 40px;
  letter-spacing: 3px;
  color:#FFF;
  transition:0.4s;
}
.arrow_box:after, .arrow_box:before {
    left: 100%;
    top: 50%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
  transition:0.4s;
}

.arrow_box:after {
    border-color: rgba(128, 128, 128, 0);
    border-left-color: gray;
  border-width: 24px;
  margin-top: -24px;
}
.arrow_box:before {
    border-color: rgba(255, 255, 255, 0);
    border-left-color: #ffffff;
    border-width: 26px;
  margin-top: -26px;
  margin-left: 2px;
}
.arrow_box:hover{
  color:#000;
  background:#FFF;
}
.arrow_box:hover:after{
  border-left-color: #FFF;
}

Проверьте скрипку здесь

Если фон, на котором находится ссылка, имеет сплошной цвет, как в приведенном примере, вы можете добиться этого с помощью пары треугольников, например, так:

*{box-sizing:border-box;font-family:sans-serif;}
body{
    background:#333;
}
a{
    border:2px solid #fff;
    border-right:0;
    color:#fff;
    display:inline-block;
    letter-spacing:3px;
    line-height:50px;
    padding:0 40px;
    position:relative;
    text-decoration:none;
    text-transform:uppercase;
    transition:background 1s ease-out,color 1s ease-out;
}
a::before{
    border-top:27px solid transparent;
    border-left:14px solid #fff;
    border-bottom:27px solid transparent;
    content:"";
    position:absolute;
    right:-14px;
    top:-2px;
}
a::after{
    border-top:25px solid transparent;
    border-left:12px solid #333;
    border-bottom:25px solid transparent;
    content:"";
    position:absolute;
    right:-12px;
    top:0;
    transition:opacity 1s ease-out;
}
a:hover{
    background:#fff;
    color:#333;
}
a:hover::after{
    opacity:0;
}
<a href="#">More</a>


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

*{box-sizing:border-box;font-family:sans-serif;}
body{
    background:#333;
}
a{
    border:2px solid #fff;
    border-right:0;
    color:#fff;
    display:inline-block;
    letter-spacing:3px;
    line-height:50px;
    padding:0 40px;
    position:relative;
    text-decoration:none;
    text-transform:uppercase;
    transition:background 1s ease-out,color 1s ease-out;
}
a::before{
    border-right:2px solid #fff;
    border-top:2px solid #fff;
    content:"";
    height:36px;
    position:absolute;
    right:-19px;
    top:6px;
    transform:rotate(45deg);
    width:36px;
}
a::after{
    background:linear-gradient(-135deg,#fff 50%,transparent 50%);
    content:"";
    height:34px;
    opacity:0;
    position:absolute;
    right:-17px;
    top:8px;
    transform:rotate(45deg);
    transition:opacity 1s ease-out;
    width:34px;
}
a:hover{
    background:#fff;
    color:#333;
}
a:hover::after{
    opacity:1;
}
<a href="#">More</a>

Другие вопросы по тегам