Как сделать необычную рамку при наведении на элемент?

1,00
р.
Как лучше реализовать такую рамку при наведении на элемент?


Ответ
Для этого можно использовать псевдоэлементы :before и :after. Например, так:


html, body { padding: 10px margin: 0px background: #1a244e } .block { width: 176px height: 246px position: relative z-index: 1 margin: 20px auto } .block:before, .block:after { content: '' position: absolute display: block width: 75px height: 195px border: green solid 2px transition: all 0.4s ease-in-out opacity: 0 visibility: hidden } .block:before { right: -5px top: -5px border-left: none border-bottom: none } .block:after { left: -5px bottom: -5px border-right: none border-top: none } .block:hover:before, .block:hover:after { opacity: 1 visibility: visible }



Можно немного поиграться со стилями и получить разные эффекты.
Вариант #1 с transform: translate():


html, body { padding: 10px margin: 0px background: #1a244e } .block { width: 176px height: 246px background: #000 position: relative z-index: 1 cursor: pointer margin: 20px auto } .block:before, .block:after { content: '' position: absolute display: block width: 75px height: 195px border: green solid 2px transition: all 0.4s ease-in-out opacity: 0 visibility: hidden } .block:before { right: -5px top: -5px transform: translate(10px, -10px) border-left: none border-bottom: none } .block:after { left: -5px bottom: -5px transform: translate(-10px, 10px) border-right: none border-top: none } .block:hover:before, .block:hover:after { opacity: 1 visibility: visible transform: translate(0, 0) }



Вариант #2 с transform: translate():


html, body { padding: 10px margin: 0px background: #1a244e } .block { width: 176px height: 246px background: #000 position: relative z-index: 1 cursor: pointer margin: 20px auto } .block:before, .block:after { content: '' position: absolute display: block width: 75px height: 195px border: green solid 2px transition: all 0.4s ease-in-out z-index: -1 opacity: 0 visibility: hidden } .block:before { right: -5px top: -5px border-left: none border-bottom: none transform: translate(-10px, 10px) } .block:after { left: -5px bottom: -5px border-right: none border-top: none transform: translate(10px, -10px) } .block:hover:before, .block:hover:after { opacity: 1 visibility: visible transform: translate(0, 0) }



Вариант #3 с width и height:


html, body { padding: 10px margin: 0px background: #1a244e } .block { width: 176px height: 246px background: #000 position: relative z-index: 1 cursor: pointer margin: 20px auto } .block:before, .block:after { content: '' position: absolute display: block width: 0px height: 0px border: green solid 2px transition: all 0.4s ease-in-out opacity: 0 visibility: hidden } .block:before { right: -5px top: -5px border-left: none border-bottom: none } .block:after { left: -5px bottom: -5px border-right: none border-top: none } .block:hover:before, .block:hover:after { width: 75px height: 195px opacity: 1 visibility: visible }



Вариант #4 на SVG:


html, body { padding: 10px margin: 0px background: #1a244e } .block { width: 176px height: 246px position: relative z-index: 1 margin: 20px auto } .border { width: 186px height: 256px display: block position: absolute left: -5px bottom: -5px } .border polyline { stroke: green stroke-width: 2px stroke-dasharray: 271 stroke-dashoffset: 271 transition: all 0.6s ease-in-out } .block:hover .border polyline { stroke-dashoffset: 0 opacity: 1 visibility: visible }



UPDATE
Вариант #5 с вынесением рамки в отдельные блоки и использованием transform: translate():


html, body { overflow: hidden padding: 10px margin: 0px background: #1a244e } .block { width: 176px height: 246px position: relative z-index: 1 margin: 20px auto } .border { position: absolute left: -5px top: -5px right: -5px bottom: -5px } .border:before, .border:after { content: '' position: absolute display: block background: green transition: all 0.2s ease-in-out opacity: 0 visibility: hidden } .border:before { width: 75px height: 2px } .border:after { width: 2px height: 195px } .border.border-rt:before, .border.border-rt:after { right: 0px top: 0px } .border.border-lb:before, .border.border-lb:after { left: 0px bottom: 0px } .border.border-rt:before { transform: translate(100%, 0) } .border.border-rt:after { transform: translate(0, -100%) } .border.border-lb:before { transform: translate(-100%, 0) } .border.border-lb:after { transform: translate(0, 100%) } .block:hover .border:before, .block:hover .border:after { opacity: 1 visibility: visible transform: translate(0, 0) }