4

Goal:

I'm creating a graphical menu with a 3D hover effect for a friend's website. There are a series of rectangles. When one is hovered over, it will move upwards and left, leaving behind a darker version of itself to appear that it's sliding outward. (The red circles in the screenshots are just to show the problem area.)

enter image description here


What I've Got:

I'm using an unordered list with a <li><a><span> structure. I currently have it moving correctly upon hover, leaving behind the shadow.

Code:

(JSFiddle Below)

HTML:

<section>
    <li class="tall" id="logos"><a class="dark" href=""><span>Logos</span></a></li>
    <li class="wide" id="illustrations"><a class="dark" href=""><span>Illustrations</span></a></li>
    <li class="wide" id="drawings"><a href=""><span>Drawings</span></a></li>
    <li class="small" id="web"><a href=""><span>Web</span></a></li>
    <li class="small narrow"  id="print"><a href=""><span>Print</span></a></li>
    <li class="small" id="other"><a class="dark" href=""><span>Other</span></a></li>
</section>

CSS:

section { //Wrap
    height:200px;
    width:600px;
}
li {
    list-style:none;
    display:block;
    float:left;
    height:47%;
    margin-bottom:2%;
}

a {
    outline:0;
    height:100%;
    width:100%;
    display:block;
    color:black;
    text-decoration:none;
    position:relative;
    top:0;
    left:0;
    box-shadow:0px 0px 0px 0px rgb(0,0,0);
    transition: all 100ms ease-in;
    background-color:inherit;
}
a:hover, a:focus {
    top:-4px;
    left:-4px;
    box-shadow:4px 4px 0px 0px rgba(0,0,0,0.2);
}
span {
    display:block;
    position:absolute;
    top:50%;
    margin-top:-15px;
    width:100%;
    text-align:center;
    font-family:Calibri;
    font-size:22px;
    font-weight:100;
}
//Sizes
.tall {
    height:100%;
    width:32%;
}
.wide {
    width:32%;
    margin-left:2%;
}
.small {
    margin-left:2%;
    width:21%;
}
.small.narrow {
    width:20%;
}
.dark {
    color:white;
}
//Colors
#logos {
    background-color:rgb(242,25,44); 
}
#illustrations {
    background-color:rgb(41,90,95);
}
#drawings {
    background-color:rgb(139,181,143);
}
#web {
    background-color:rgb(187,222,189);
}
#print {
    background-color:rgb(239,243,210);
}
#other {
    background-color:rgb(242,25,44);
}

Screenshot:

enter image description here

Fiddle:

http://jsfiddle.net/LhkEp/9/


What I Need:

I need to figure out how to get the corners to look diagonal. It you notice the difference between the two pictures, my current version doesn't have them connected. Is this possible? Thanks for the help!


EDIT:

I've gotten 2 different methods for creating the triangle piece with color, but both require some tweaking to get exactly what I want. I'm not sure which is going to be simpler in the end, and look better when animating. I'm going to spend some time playing around with them and report back which I end up using. Thank you to everyone who answered. (If you have a different idea than what has been proposed, please feel free to add another answer.)

EDIT 2:

Using web-tiki's method, I've gotten it totally working here: http://jsfiddle.net/LhkEp/23/ This I think is the best method because there are no glitches, and everything looks perfect even if you slow down the animation. Also by changing to use the wrap for all selection, there is no back and forth if you are just hovering over the shadow.

web-tiki
  • 99,765
  • 32
  • 217
  • 249
Kelderic
  • 6,502
  • 8
  • 46
  • 85

4 Answers4

3

You can use borders to make the triangles (here is a post that explains the technique in detail : How does this CSS triangle shape work? ) on the top-right and bottom left and animate their position on hover to create the coming out effect.

In the following demo, I made the effect with red triangles so you can see how the move on hover. You can then adapt it to fit your need and change the border color to match each menu item's shadow :

DEMO

This is the CSS I added :

a:before, a:after{
    content:'';
    position:absolute;
    transition: right 100ms ease-in, bottom 100ms ease-in;
}
a:after{
    top:0; right:0;
    border-bottom:2px solid red;
    border-left:2px solid red;
    border-right:2px solid transparent;
    border-top:2px solid transparent;
}
a:hover:after{
    right:-3px;
}
a:before{
    bottom:0; left:0;
    border-top:2px solid red;
    border-right:2px solid red;
    border-left:2px solid transparent;
    border-bottom:2px solid transparent;
}
a:hover:before{
    bottom:-4px;
}
Community
  • 1
  • 1
web-tiki
  • 99,765
  • 32
  • 217
  • 249
  • @Ruddy added explanation – web-tiki Jul 21 '14 at 14:44
  • I like this, except that I'm having trouble getting the color to match. You've got it so that it is just red. I've tried placing `inherit` but that is bringing up white. – Kelderic Jul 21 '14 at 14:53
  • @AndyM Here, I made it more simple to customize the border colors http://jsfiddle.net/webtiki/LhkEp/15/ I made it for the logo item, you should manage to do it for the other men items – web-tiki Jul 21 '14 at 15:01
  • @AndyM here, I added animation to the border-width and made it the same color as the shadow (only on the logo menu item) http://jsfiddle.net/webtiki/LhkEp/16/ – web-tiki Jul 21 '14 at 15:09
  • Gotcha. I'm playing around with trying to get the colors to inherit, so that I only have to declare them once. I think your method is the closest to what I want. – Kelderic Jul 21 '14 at 15:10
  • @AndyM maybe you could take a look at `currentColor` although I'm not shure browser support is awesome http://css-tricks.com/currentcolor/ – web-tiki Jul 21 '14 at 15:13
  • @AndyM in fact, no need to animate border-width, it makes it wierd, you can use z-index to hide pseudo elements behind the a element : http://jsfiddle.net/webtiki/LhkEp/17/ – web-tiki Jul 21 '14 at 15:32
  • Your answer and SW4's are both very different approaches, and both are going to require me to work a bit to implement. My goal is to declare each color only once. I was able to get away with the darker color because of the opacity of the shadow. I don't think that I can get this method to work without requiring the color to be declared twice. I'll have to play around with it more to see, though, so I'm not going to select an answer yet because I'm not sure which method I'll use. I very much appreciate your help though! – Kelderic Jul 21 '14 at 16:04
  • The only way I think I can do it is to use inherit, which I got work, plus a shadow on the triangle part. If I can get it working with this method, I'll let you know. – Kelderic Jul 21 '14 at 16:04
  • @AndyM yes, CSS isn't realy a programming language and I am not aware of a method to reuse a color without redeclaring it other than the `currentColor` method. Otherwise you will have to look into css pre-processors like Less , scss... – web-tiki Jul 21 '14 at 16:12
  • I've got it entirely working here, based on your method. I used 2 puesdo elements for color, and 2 for darkening, based on the before and after of the `a` and `li`. http://jsfiddle.net/LhkEp/19/ The only issue I'm running into now is that if you hover on the darkened part, you are triggering the `li:hover` and not the `a:hover` which causes a glitch. – Kelderic Jul 21 '14 at 18:04
2

This can be accomplished using pseudo elements and some CSS border trickery...the crucial part being that the intersection of borders at corners is mitred which produces the angle required.

Throw in a few transitions for :hover et voila!

Demo Fiddle

Demo Fiddle with your code (and more complex, smoother animation)

div {
    height:50px;
    width:50px;
    position:relative;
    background:pink;
    top:0;
    left:0;
    transition:all 100ms ease-in;    
}
div:hover{
    top:-4px;
    left:-4px;
}
div:hover:before, div:hover:after{
    opacity:1;
}
div:before, div:after {
    content:'';
    display:inline-block;
    position:absolute;
    opacity:0;
    transition:opacity 100ms ease-in;
}
div:after {
    height:100%;
    right:-4px;
    border-top:4px solid white;
    border-left:4px solid red;
}
div:before {
    width:100%;
    height:4px;
    top:100%;
    border-left:4px solid white;
    border-top:4px solid red;
}
SW4
  • 69,876
  • 20
  • 132
  • 137
  • I like this except for the fact that the shadow itself moves, due to the fact that it fades in, and fades in from below, then moves upwards. I get a joggy effect on it. – Kelderic Jul 21 '14 at 14:59
  • @AndyM can you clarify? Its all easily configurable. – SW4 Jul 21 '14 at 15:15
  • Sorry, yes that second one does fix the movement problem, but now has a white flash. – Kelderic Jul 21 '14 at 15:30
  • Your answer and web-tiki's are both very different approaches, and both are going to require me to work a bit to implement. My goal is to declare each color only once. I was able to get away with the darker color because of the opacity of the shadow. I don't think that I can get this method to work without requiring the color to be declared twice. I'll have to play around with it more to see, though, so I'm not going to select an answer yet because I'm not sure which method I'll use. I very much appreciate your help though! – Kelderic Jul 21 '14 at 16:03
2

This is kind of simple, not sure if you know that you can apply multiple shadow, so all you need to do is as below:

a:hover, a:focus {
    top:-4px;
    left:-4px;
    box-shadow:1px 1px 0px 0px rgba(0,0,0,0.2),//Change here
        2px 2px 0px 0px rgba(0,0,0,0.2),//Change here
        3px 3px 0px 0px rgba(0,0,0,0.2),//Change here
        4px 4px 0px 0px rgba(0,0,0,0.2);//Change here
}

The "diagonal" seems quite light unlike your illustration image because you apply an opacity 0.2 here which you can change.

WORKING DEMO HERE

Godinall
  • 2,280
  • 1
  • 13
  • 18
  • The problem with this is that the diagonal parts are gray, because they are adding transparent black over white, not over the `li` below. – Kelderic Jul 21 '14 at 14:51
  • @AndyM that you can change in the rgba color I believe? – Godinall Jul 21 '14 at 15:03
  • My goal is to declare each color only once. I can get away with the darker colors on the side and bottom by using dark opacity. I need the color and the shadow though, and this method doesn't provide the color for the triangle. However, it DOES do the shadow, which other methods don't. Maybe I can combine them? Anyway though, thank you for the help! – Kelderic Jul 21 '14 at 16:06
1

This can be achieved by using border-radius for a:hover and li:hover :

border-radius:0 5px 0 5px;

http://jsfiddle.net/LhkEp/13/

ColonelMo
  • 134
  • 1
  • 9
  • 1
    This ends up making a bunch of curves, which isn't exactly what I want. However, +1 for the idea, which was completely different and interesting. Thanks! – Kelderic Jul 21 '14 at 16:06
  • No need to apologize, it was an interesting idea which involves much simpler code. – Kelderic Jul 21 '14 at 18:32