1

it's been a while! I am currently trying to solve a problem and I was hoping somebody could help me out. I have a fixed sidebar and a header. Both cast dropshadow. However, I don't want the header to cast shadow on the sidebar (I want them to be on the same level). At the same time, header contains drop-downs and these need to hover over everything. Since it's rather complex, I've created a jsfiddle.

Simple example

I've been forced to paste the code here as well for some reason (SO input validation).

<div class="layout">
  <div class="header z-depth-2">
    <div class="dropdown-toogle">
      <div class="dropdown-menu">
      </div>
    </div>
  </div>
  <div class="page-wrapper">
    <div class="sidebar z-depth-2">
    </div>
    <div class="content">
    </div>
  </div>
</div>

And css

.layout {
  width: 100%;
  height: 100%;
  position: relative;
}

.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 70px;
  background-color: blue;
  z-index: 101;
}

.sidebar {
  position: fixed;
  top: 70px;
  left: 0;
  width: 200px;
  background-color: green;
  bottom: 0;
  z-index:101;
}

.content {
  padding-left: 200px;
  width: 100%;
  height: 100%;
}

.page-wrapper {
  padding-top: 70px;
  height: 100%;
}

.dropdown-toogle {
  margin-right: 100px;
  float: right;
  position: relative;
  height: 100%;
  width: 50px;
  background-color: yellow;
}

.dropdown-menu {
  position: absolute;
  top: 100%;
  right: 0;
  width: 400px;
  height: 200px;
  background-color: grey;
  z-index:1000;
}

.z-depth-2 {
  box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
}

Notice how when you change view-port width, drop-down slides behind sidebar even when it's z-index is greater.

If I increase z-index of header, it starts casting shadow on the sidebar (drop-down starts working) which I want to avoid. I've been playing with different combination but was unable to sort it out properly.

Hope I managed to make it clear, help much appreciated!

Peter Kottas
  • 733
  • 9
  • 23
  • Are you married to using those fixed positions? I could offer an alternative way to get an identical layout. Not sure if that's really what you want though. – Don Aug 01 '17 at 20:20
  • Not really married to it but it seems like sensible approach. I now checked your answer and replied there as well :) Thanks again! – Peter Kottas Aug 02 '17 at 12:19

2 Answers2

2

With your current layout this isn't possible. Since the header is set to a z-index behind the sidebar essentially any child of the header will also be behind the sidebar. (Read more on stacking contexts)

In order to solve this issue what you can do is use an inset box-shadow on the content pane. This will make it so there is a shadow as if it's being cast by the header and sidebar but it's really the container casting it on itself. This way you don't need to worry about the header casting onto the sidebar and the sidebar can safely sit "behind" the header. With this you don't need to fiddle with z-index at all (though I didn't remove them in case it's needed for other things on the page).

In order to get this to work properly I had to change the padding you were using to position the content element with margin but honestly this is a better property to use for adding space around an element. I recommend you also read up a bit on when to use padding vs margin.

https://jsfiddle.net/79gykeu3/6/

HTML

<div class="layout">
  <div class="header z-depth-2">
    <div class="dropdown-toogle">
      <div class="dropdown-menu">
      </div>
    </div>
  </div>
  <div class="page-wrapper">
    <div class="sidebar z-depth-2">
    </div>
    <div class="content">
    </div>
  </div>
</div>

CSS

The thing to note is the .content class now has the box-shadow

html {
  height: 100%;
}

body {
  width: 100%;
  height: 100%;
  margin: 0;
}

.layout {
  width: 100%;
  height: 100%;
  position: relative;
}

.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 70px;
  background-color: blue;
  z-index: 103;
}

.sidebar {
  position: fixed;
  top: 70px;
  left: 0;
  width: 200px;
  background-color: green;
  bottom: 0;
  z-index:101;
}

.content {
  margin-left: 200px;
  width: 100%;
  height: 100%;
    box-shadow: inset 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
}

.page-wrapper {
  margin-top: 70px;
  height: 100%;
}

.dropdown-toogle {
  margin-right: 100px;
  float: right;
  position: relative;
  height: 100%;
  width: 50px;
  background-color: yellow;
}

.dropdown-menu {
  position: absolute;
  top: 100%;
  right: 0;
  width: 70%;
  height: 200px;
  background-color: grey;
  z-index:1000;
}

.z-depth-2 {
}
Don
  • 3,581
  • 12
  • 32
  • 1
    Didn't want to put it in the answer as it's an aside, but really this page layout should be looked at. It would be much better to have the elements not positioned with fixed and just have the content div be scrollable, while the header and sidebar remain on the page but it seemed outside the scope of the question. – Don Aug 01 '17 at 20:36
  • Hey man, thanks for the awesome reply! I really appreciate the work you put into it and you explained it very well. Reason I go with this layout is this is a typical dashboard application. Sidebar is actually scrollable and the content scrolls as well. Sidebar is collapsible, that's why I went with padding instead of margin. Margin pushes content while padding get's width 100% and only pushes inner content away from the side. Sidebar is animated (collapsible) and width: calc(100% - 300px) and margin-right: 300px doesn't animate on IE. – Peter Kottas Aug 02 '17 at 12:17
  • However, you inspired a solution that sounds like something I'll probably use. I'll just add 2 stripes with a gradient. One on the bottom of the header, one on the side of the sidebar. That will in effect look like shadow but it wouldn't scroll as I'll position it absolutely in context of header and sidebar. Will implement it and let you know. – Peter Kottas Aug 02 '17 at 12:19
  • Ok, check this out, what do you think? https://jsfiddle.net/79gykeu3/8/ – Peter Kottas Aug 02 '17 at 12:28
  • you can use a relative position with the calc'd width, change the left property and the width, both of those should animate on IE: https://jsfiddle.net/79gykeu3/9/ – Don Aug 02 '17 at 14:39
  • This is my proposed alternate layout. Avoiding all the craziness with the fixed positioning. Sidebar scrolls and is collapsible even in IE the `flex-basis` property should animate: https://jsfiddle.net/79gykeu3/10/ – Don Aug 02 '17 at 14:47
  • I've accepted your answer and provided the solution that I used as well – Peter Kottas Aug 02 '17 at 17:07
0

First of all, big thanks goes to Don, his approach is totally valid, clever and possibly even better than what I used. However I figured I'll post my final solution as well as somebody might value having 2 approaches. All I did is I've added a "fake" gradient absolutely positioned bellow the header and to the right of sidebar. The reason why I've done so is basically I used technologies that I know and can rely on. I didn't like the overflow auto on the content as well. Anyways, this is it:

https://jsfiddle.net/79gykeu3/11/

<div class="layout">
    <div class="header">
        <div class="header__shadow">
        </div>
        <div class="dropdown-toogle">
            <div class="dropdown-menu">
            </div>
        </div>
    </div>
    <div class="page-wrapper">
        <div class="sidebar">
            <div class="sidebar__shadow">
            </div>
        </div>
        <div class="content">
        </div>
    </div>
</div>

Css

.layout {
    width: 100 %;
    height: 100 %;
    position: relative;
}

.header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 70px;
    background - color: blue;
    z - index: 103;
}

.sidebar {
    position: fixed;
    top: 70px;
    left: 0;
    width: 200px;
    background - color: green;
    bottom: 0;
    z - index:101;
}

.content {
    padding - left: 200px;
    height: 8000px;
}

.page - wrapper {
    padding - top: 70px;
    height: 100 %;
}

.dropdown - toogle {
    margin - right: 100px;
    float: right;
    position: relative;
    height: 100 %;
    width: 50px;
    background - color: yellow;
}

.dropdown - menu {
    position: absolute;
    top: 100 %;
    right: 0;
    width: 400px;
    height: 200px;
    background - color: grey;
    z - index:1000;
}

.header__shadow {
    position: absolute;
    height: 7px;
    left: 200px;
    right: 0;
    top: 100 %;
    background: linear - gradient(to bottom, rgba(0, 0, 0, 0.35) 0%,rgba(0, 0, 0, 0) 100%);
}

.sidebar__shadow {
    position: absolute;
    left: 100 %;
    top: 0;
    bottom: 0;
    width: 7px;
    background: linear - gradient(to right, rgba(0, 0, 0, 0.35) 0%,rgba(0, 0, 0, 0) 100%);
}
Peter Kottas
  • 733
  • 9
  • 23
  • 1
    For sure man, if you like it go for it. I just think the less complicated the dom, the better. But if you like and can wrap your head around this better go for it. Glad you found something that works. – Don Aug 02 '17 at 19:26