Shadow on a floating menu

Hi,

I am sure everyone of you had used, at least once, Google Docs. When you go on File and click to show the menu you will see the nice shadow effect on menu trigger and menu. I am wondering how they do it, I didn’t figured a way to have that effect without adding a new ghost element for the menu trigger which can accept z-index and appear 1px over the menu.

Looking forward to find out your thoughts.

Regards,
Iulian

Looks like you are talking about CSS3 box-shadow, if I understand rightly, but I’m not sure what you are referring to.

Ralph, thanks for looking into this. Yes, it’s the box-shadow property, but how do I get rid of the bottom border under File? “File” element and menu container element have different parents.

See attached image.

Google makes it hard to see how they’ve done it because it’s all done with pretty messy JS, but one option would be to use the :after pseudo element to create a little white patch that covers over the shadow at the bottom of the link.

I will look into the :after pseudo-element and I will post here any solution I find. If you have any example in your mind, I would appreciate if you could post it.

Regards,
Iulian

The best thing to do would be to get your dropdown as close to working as you can, and then we can help you get the box shadow working. It’s easier to help with the actual code you are using. :slight_smile:

If you can’t post a link to your current work, then try to post a code example here, using a template like this:

Drop down is working but I cannot remove the line mentioned in my previous messages.

I have attached a HTML snippet which reproduces the structure I’m having in my code.


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
	
<style>

body {
    font-family: arial;
}

.menu-trigger {
    border: solid 1px #000;
    box-shadow: red 0 2px 4px;
    position: absolute;
    top: 40px;
    left: 40px;
    height: 30px;
    z-index: 1000;
    width: 50px;
}

.menu {
    width: 200px;
    position: absolute;
    top: 71px;
    left: 40px;
    z-index: 1001;
    border: solid 1px blue;
    background-color: white;
    box-shadow: red 0 2px 4px;
}

</style>
	
</head>
<body>

    <div class="toolbar">
        <div class="menu-trigger" id="file-button">File</div>
    </div>

    <div class="menu" id="file-menu">
        <div class="menu-item">Save</div>
        <div class="menu-item">Save As...</div>
        <div class="menu-item">Export</div>
    </div>

</body>
</html>

Below is a solution. Not the best one as I’m using JS to size the menu-invisibleline element.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
 
<style>
 
body {
    font-family: arial;
}
 
.menu-trigger {
    border: solid 1px #000;
    box-shadow: red 0 2px 4px;
    position: absolute;
    top: 40px;
    left: 40px;
    height: 30px;
    z-index: 1000;
    width: 50px;
}
 
.menu {
    width: 200px;
    position: absolute;
    top: 71px;
    left: 40px;
    z-index: 1001;
    border: solid 1px blue;
    background-color: white;
    box-shadow: red 0 2px 4px;
}

.menu-invisibleline {
    position: absolute;
    width: 50px;
    background-color: white;
    top: -2px;
    height: 2px;
    left: 0px;
}
 
</style>
 
</head>
<body>
 
    <div class="toolbar">
        <div class="menu-trigger" id="file-button">File</div>
    </div>
 
    <div class="menu" id="file-menu">
        <div class="menu-item">Save</div>
        <div class="menu-item">Save As...</div>
        <div class="menu-item">Export</div>
        <div class="menu-invisibleline"></div>
    </div>
 
</body>
</html>

first of all,

Your menu should be structured as an unordered list. making your code semantic, it will work to your benefit whether or not you get your site looking like you want to :wink:

as far as the styling… maybe this is what you were looking for?


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
 
<style type="text/css">
ul{padding:0; margin:0; list-style:none;} /* a reset*/
body {
    font-family: arial;
}


.toolbar li {padding: 3px 6px;}
.menu-trigger {
    border: solid 1px transparent;
     position: relative;
    max-width: 150px;
    float:left;
}
.menu-trigger:hover {
    border-color:   #000;
    box-shadow: red 0 0 3px;
 }
.menu-trigger:hover:after {
    position: absolute;
 	left:0;
	right:0;
	bottom: -3px;
	height:5px;
	background: #fff ;
	z-index: 20;
	content:'';
	  
 }

.menu-trigger ul  {
    width: 200px;
    position: absolute;
    top: 100%;
    left:-99999em;
    border: inherit;
    background-color: white;
    box-shadow: red 0 0 3px;
    z-index: 19;
    padding-top:5px;
}
.menu-trigger:hover ul  {
     left:-1px;
 }
 
 
</style>
 
</head>
<body>
 
    <ul class="toolbar">
        <li class="menu-trigger" id="file-button">File
		    <ul class="menu" id="file-menu">
		        <li class="menu-item">Save</li>
		        <li class="menu-item">Save As...</li>
		        <li class="menu-item">Export</li>
		        <li class="menu-invisibleline"></li>
		    </ul>
        </li>
        <li class="menu-trigger" id="file-button">File
		    <ul class="menu" id="file-menu">
		        <li class="menu-item">Save</li>
		        <li class="menu-item">Save As...</li>
		        <li class="menu-item">Export</li>
		        <li class="menu-invisibleline"></li>
		    </ul>
        </li>
        <li class="menu-trigger" id="file-button">File
		    <ul class="menu" id="file-menu">
		        <li class="menu-item">Save</li>
		        <li class="menu-item">Save As...</li>
		        <li class="menu-item">Export</li>
		        <li class="menu-invisibleline"></li>
		    </ul>
        </li>
    </ul>
 
 
</body>
</html>

The sticky/clicking part will require either .js ( to to switch classes on elements) or some unsemantic markup which I would generally steer clear of, besides it would also limit your browser support.

hope that helps

dresden_phoenix, your solution is also valid and I would recommend it for any application where the elements can be structured this way. Most of the websites probably are doing it this way. In case of web apps is a little different, as you may be constrained by the framework to not follow the semantics.

In my HTML code above I tried to reproduce the conditions that create the problem, which is that the menu trigger and the floating menu are rendered in different parents, in which case z-index and other tricks cannot be applied.

Iulian

would your framework permit the menu-triggers and menus to be wrapped within the same container , even if not adjacent? You may be able to use the general sibling selector (~) that way. If you are stuck with this exact mark up, am afraid then that ralph is right and.js would be the only way.

Sidenote: I am a little lost as to why a web app coded in HTML would WANT to follow HTML convention, but we get stuck with the client we get stuck with

Using your html why can’t you just do it like this:?


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body { font-family: arial; }
.menu-trigger {
	border: solid 1px #000;
	box-shadow: red 0 2px 4px;
	position: absolute;
	top: 40px;
	left: 40px;
	height: 30px;
	width: 50px;
}
.menu {
	width: 200px;
	position: absolute;
	top: 71px;
	left: 40px;
	border: solid 1px blue;
	background-color: white;
	box-shadow: red 0 2px 4px;
}
.menu-trigger:after {
	content:" ";
	position: absolute;
	bottom:-4px;
	height:8px;
	background:#fff;
	left:0;
	right:0;
	z-index:1002;
}
</style>
</head>
<body>
<div class="toolbar">
		<div class="menu-trigger" id="file-button">File</div>
</div>
<div class="menu" id="file-menu">
		<div class="menu-item">Save</div>
		<div class="menu-item">Save As...</div>
		<div class="menu-item">Export</div>
</div>
</body>
</html>

Remove the z-indexes from the main containers and just use the :after element (with a z-index) on the tab to rub out the line. Using left and right it will auto size to the tab automatically.

Paul, your solution was exactly what I was looking for. I am not accustomed to the use of :after, so there were very few to none chances to come up with this on my own. I know it doesn’t work on older browsers, but that’s fine…

Thanks and regards,
Iulian

:after works in IE8+ but of course box-shadow only works in ie9+ anyway.:slight_smile: