Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parent inset box-shadow overlapped by children divs

Tags:

html

css

I am having an issue where the children divs are overlapping the parents box-shadow bottom.

The parent has a max-height w/ overflow-y: scroll. Any help would be great!

http://i.stack.imgur.com/jQe0r.png

HTML:

<div class="capture sh-btm">
  <div class="threads">
    <div class="thread"></div>
    <div class="thread"></div>
    <div class="thread"></div>
    <div class="thread"></div>
  </div>
</div>

CSS:

.capture {
  width: 100%;
  height: 100%;
  overflow-y: scroll;
  overflow-x: hidden;
  position: relative;
}

.threads {
  height: 250px;
  width: 100%;
  display: inline-block;
  padding-bottom: 10px;
  position: relative;
  clear: left;
}

.thread {
  width: 248px;
  float: left;
  margin-right: 8px;
  margin-top: 6px;
  border-bottom: 2px solid #dadada;
  overflow: hidden;
  zoom: 1;
}

.sh-btm {
  box-shadow: inset 0px -5px 9px -2px #000;
}
like image 356
cloudstrife Avatar asked May 21 '13 23:05

cloudstrife


2 Answers

No, what you're asking can be done quite easily. However, for ease I would advise for using a background-image or a CSS gradient instead of inset box-shadows. You'll have to tweak the CSS a bit to get exactly what you wanted. (for example to make sure the bottom overlay doesn't cover the bottom arrow of your scrollbar).

Setting a z-index on the child elements will only work if you have nothing more than static text and images to show, and no links or interactive content. You're also not allowed to set a background for the parent, or it will hide the children.

To achieve this, you need to make 2 separate shadow overlay divs, and position them absolutely in a parent container. Your structure will be like this:

  • Parent container
    • Shadow overlay left
    • Shadow overlay bottom
    • Threadcontainer (overflow is set on this div)
      • Thread
      • Thread

Here is a working demo: http://jsbin.com/avafaq/1/edit

<div class="capture sh-btm">
  <div id="shadow_overlay_left"></div>
  <div id="shadow_overlay_bottom"></div>
  <div class="threads">
    <div class="thread"></div>
    <div class="thread"></div>
  </div>
</div>
#shadow_overlay_left{
  width: 10px;
  height: 100%;
  position: absolute;
  z-index: 5;
  box-shadow: inset 3px -2px 5px 0px #000;
}
#shadow_overlay_bottom{
  width: 100%;
  min-height: 10px;
  position: absolute;
  bottom: 0%;
  z-index: 5;
  box-shadow: inset 0px -5px 9px 0px #000;
}
.threads {
  overflow-y: scroll;
  overflow-x: hidden;
}

Notice I put the overflow properties on the .threads container instead of the parent container. This is because else your absolutely positioned divs will scroll too, and will not fill their respective widths/ heights.

Again, you can apply box-shadow, a background-image or CSS gradients to your shadow overlay divs.

like image 199
webketje Avatar answered Oct 11 '22 16:10

webketje


You can do it with positioning and box-shadow alone, but browser support would be poor. I used position: sticky (no Chrome support), but a fun experiment anyway.

<div class="wrap">
<!-- We set the overflow on the parent -->
    <div class="shadow"></div>
    <!-- Create a new container as a layer over the rest of the content -->
    <div class="content">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
    </div>
</div>

Use position: sticky instead of absolute, .shadow will stay at the top of its parent as long as the parent is visible, so we set it up with the full height of the parent and offset the content with a negative margin to align it with the top of the parent. Sticky doesn't scroll down with the content like an absolute positioned element would.

You can now set the inset box-shadow to any value and use pointer-events: none to allow interaction with the layer behind the layer with the box-shadow (because positioned elements with a higher z-index will prevent you from interacting with elements behind them).

.wrap{
  border: 1px solid #dadada;
  /* You'll need a fixed height - assuming that's the case already, given the overflow */
  height: 400px;
  margin: 5vh auto;
  overflow-y: auto;
  width: 50vw;
}
.content{
  margin-top: -400px;
}
.shadow{
  box-shadow: 10px -10px 10px rgba(0, 0, 0, 0.3) inset;
  height: 100%;
  /* To avoid objects below not being accessible we use pointer events - CSS4 and wonky IE support again */
  pointer-events: none;
  position: sticky;
  /* Firefox doesn't really need the vendor prefix and Chrome doesn't support this */
  position: -webkit-sticky;
  position: -moz-sticky;
  position: -ms-sticky;
  position: -o-sticky;
  top: 0;
  width: 100%;
}
.item{
  /* You would obviously add your own styling - just making boxes that show the concept */
  background: white;
  border: 1px solid #dadada;
  box-sizing: border-box;
  float: left;
  height: 250px;
  margin: 1%;
  width: 23%;
}
.item:hover{
  /* To demonstrate the click through the top layer and :hover works */
  background: #f3f3f3;
}

Again - this is experimental and browser support is lacking in places, but proves that you can do it with CSS only.

Fiddle here ...

like image 28
Jayx Avatar answered Oct 11 '22 15:10

Jayx