Parent inset box-shadow overlapped by children divs - html

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;
}

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.

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 ...

The problem is that the child elements are higher in the stacking context that the parent. To make the shadow show through, you need to make them lower than the parent.
First of all you need to position the element to make z-index apply, then reduce the z-index to a value lower than the parent. Eg.
.thread {
position: relative;
z-index: -1;
}
http://jsfiddle.net/7PhfJ/
Or as .threads is already positioned, and the box-shadow is on its parent, you can add the z-index directly on that element:
.threads {
z-index: -1;
}
http://jsfiddle.net/7PhfJ/1/

Related

Box-shadow not displaying and flex container not stretching

I'm not sure if this is allowed, but my question can actually be splitted into two:
The bottom header should display a bottom box-shadow, but doesn't because of backgrounds and z-index (if I'm correct).
The container should occupy 100% of remaining available screen height. If the content in container right is longer, stretch both container and container right. container left should always be 100% remaining available height, stay on screen, and display a scrollbar if the content is too long for the container.
As you can see in the situation screenshot below, currently I'm not able to do either.
How can I fix both of these issues? I've been messing around trying various solutions, but none of them seem to work 100%.
Do note that there's a certain layering order:
Container > Header(s) + Footer > Sidepanel > Modal
Here's the situation: Codepen example
I've only included the relevant code here for the sake of brevity.
HTML:
<div class="header-box-shadow">Header 1</div>
<div class="header-box-shadow">Header 2</div>
<div class="header-box-shadow">Header 3</div>
<div class="header-box-shadow">Header 4</div>
<div class="container">
<div class="content">
<div class="left">container left</div>
<div class="right">container right</div>
</div>
</div>
<div class="footer">footer</div>
<div class="sidepanel">sidepanel</div>
<div class="modal">modal</div>
SCSS:
.header-box-shadow {
&:last-of-type {
box-shadow: 0 2px 4px rgba(0, 0, 0, .3);
position: relative;
z-index: 100000;
}
}
.container {
display: flex;
flex-direction: column;
.content {
flex: 1 1 auto;
display: flex;
.left {
height: 100%;
}
.right {
flex: 1 1 auto;
}
}
}
.footer {
position: fixed;
bottom: 0;
left: 0;
}
.sidepanel {
height: 100%;
position: fixed;
top: 0;
right: 0;
}
.modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Wrap your complete HTML layout inside another div, which you give display: flex. You can then give this div, let's call it .outer, 100% viewport height. Then, on the container, set flex: 1; - this will make sure that the container stretches and fills remaining vertical space. You can then also remove the footers fixed position. Next, set overflow-y: scroll; on the left container side. It will scroll when the content gets too large.
For your box shadow, :last-of-type will not work, because the last div is not the last of it's type in the parent container. Therefore, add a class .last to the last header item and apply the box shadow to that selector.
Have a demo here: https://codepen.io/NikxDa/pen/vdZbxV?editors=1100
Please let me know if this is the result you were trying to achieve.
One problem is I think that last-of-type selector only works on node-selectors like in this answer is described.
After compiling your scss there is .header-box-shadow:last-of-type { and because of the class it doesn't work.
So if you make an extra class for the element with the shadow, it will work.
.hasShadow{
box-shadow: 0 2px 4px rgba(0, 0, 0, .3);
position: relative;
z-index: 100000;
}

Stacking borders in CSS

I'm filling a parent div with dynamically generated child divs. I'd like for the child divs to be bound by the parent (so they can't expand the parent's shape horizontally as they fill with content). At the same time, I'd like for the child div borders to sit on top of the parent div borders, as well as each others. I threw together a diagram to better explain:
What is the best way to accomplish this via CSS? I've looked around, and I can't seem to find a solution that both stacks the borders, but also keeps the child divs restricted by the parent div (on the x axis).
Overlapping borders are always a little tricky. In your case, I wouldn't recommend working with absolute positions and z-indexes – this will only make things more complicated and you won't be able to rely on the native behaviour of block elements anymore.
Let's say your HTML looks like this:
<div class="parent">
<div class="child yellow"></div>
<div class="child blue"></div>
<div class="child red"></div>
</div>
You can achieve the illusion of overlapping children by only applying a top border to the :first-child. Even if you add more divs dynamically to the top, the first one will always be the one that appears to be "on top":
.child {
border-style: solid;
border-width: 0 2px 2px 2px;
background: white;
}
.child:first-child {
border-top-width: 2px;
}
.yellow {
border-color: yellow;
}
.blue {
border-color: blue;
}
.red {
border-color: red;
}
The parent needs a little hack, because if you added a regular border around it, it would be displayed around the children.
.parent {
width: 500px; /* or any other width */
height: 100vh; /* or any other fixed height */
overflow-y: auto; /* make scrollable */
box-shadow: inset 2px 2px 0 black, inset -2px -2px 0 black;
}
The inset box-shadow creates the illusion of solid border on the inside of the parent. To make sure it's not visible underneath the children borders (box-shadows tend to be slightly blurrier than borders), you need to make sure the children have a background colour.
Edit: Here's a demo.
You can influence the stack order in css with z-index but you need to use a position:absolute or position:fixed on these elements.
.div1 {
width: 200px;
height: 100px
position: absolute;
top: 0;
left: 0;
z-index: 1
}
.div2 {
width: 200px;
height: 100px
position: absolute;
top: 190px;
left: 0;
z-index: 2
}
That css should display the .div2 10px overlapping the .div1
If the height is dynamic you can either add it by JS or add on div as child in the next.
Note that each "position" attribute relates to the recent parent position relative or absolute!
If I understand you right, you could place the border of the parent using :after and position absolute, with z-index:-1:
.parent { position: relative; }
.parent:after {
content: '';
position: absolute;
z-index: -1;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
border: 1px solid black;
}
and for the children, you could remove the top border if not the :
first:
.child:not(:first-child) {
border-top: 0;
}
you can also try this one. Define two different classes. "Border" class for border width and style. And a color class. Like this:
<style>
.border {
border: 5px solid;
}
.green {
border-color: green;
border-top-width: 0px;
}
.yellow {
border-color: yellow;
}
/*I do not use a border-top-width to remowe top because this is the first div.*/
.red {
border-color: red;
border-top-width: 0px;
}
</style>
<div class="container">
<div class="border yellow">yellow</div>
<div class="border green">green</div>
<div class="border red">black</div>
</div>

z-index wont work positions

I'm trying to achieve that the erf_fromto would have a higher z-index than left_side, cause left_side do have a border, while i want the erf_fromto to be over the border.
this is how it looks like currently, while I want the erf_fromto to be over the line.
<body class="parent" ng-app="myApp">
<div class="left_side child"></div>
<div class="right_side">
<div class="erf_block" style="position:relative;">
<div class="erf_fromto">2011 - 2012</div>
</div>
</div>
</body>
css:
.left_side {
width:35%;
float:left;
border-right: 3px solid #F6F6F6;
}
.parent {
overflow: hidden;
position: relative;
}
.child {
height: 100%;
position: absolute;
}
.erf_fromto {
position: absolute;
left: -122px;
border: 2px solid #F6F6F6;
padding: 5px;
font-weight: bold;
box-shadow: 0px 0px 2px #F6F6F6;
font-size: 15px;
z-index: 99;
overflow: hidden;
}
codepen: http://codepen.io/anon/pen/XjzwdN
z-index applies to an element and it's children. Since .erf_fromto is nested inside .erf_block, which is inside .right_side you'll want to ensure that it's .right_side that has the higher z-index than .left_side!
From MDN:
The z-index property specifies the z-order of an element and its descendants. When elements overlap, z-order determines which one covers the other. An element with a larger z-index generally covers an element with a lower one.
If you also put a position: relative; and z-index:0; to the .left_side child it will work
Maria,
If you add a background to left_side and erf_fromto you will see they are on the correct position.
I think you just need add background property on your erf_fromto class:
.erf_fromto {
...
background: white;
...
}
I hope it helps...
Good Luck!

Absolute positioned div breaks on relative parents edge

I am experiencing some trouble while positioning an absolute div inside a relative one. I want my absolute div (inline-block) to grow until it reaches a given px-amount (max-width). This works as expected, until I add a width (smaller than the max-width of the absolutes div) to the relative div.
I want the text in the absolute-div to break at the max-width (400px) and not at the edge of the relative parent div (300px).
When giving white-space: nowrap, the words just flow over the absolute divs end.
Have anyone an idea how to solve this?
Thanks!
See:
http://codepen.io/anon/pen/KVJvmZ
html
<div class="relativeContainer">
<div class="absoluteContainer">
Hello you! This breaks on relativeContainers edge.. This is not what i want. It should just go further an further (until it reaches max-width of 400px).
</div>
</div>
<div class="relativeContainer">
<div class="absoluteContainer">
This should stay small.
</div>
</div>
css
.relativeContainer {
width: 300px;
height: 100px;
border: 1px solid black;
position: relative;
margin-bottom: 50px;
}
.absoluteContainer {
display: inline-block;
position: absolute;
top: 0;
left: 0;
max-width: 400px; /* Word-break should happen here. */
border: 1px solid red;
}
I am afraid it is not possible to solve this issue with your markup. But there is light at the end of the tunnel: You could change your markup or use javascript to achieve what you want.
Depending on your requirements, this could help you: http://codepen.io/anon/pen/eJXYOJ
html
<div class="relativeContainer">
<div class="absoluteContainer">
<div class="contentContainer">
Hello you! This breaks on relativeContainers edge.. This is not what i want. It should just go further an further (until it reaches max-width of 400px).
</div>
</div>
</div>
<div class="relativeContainer">
<div class="absoluteContainer">
<div class="contentContainer">
This should stay small.
</div>
</div>
</div>
css
.relativeContainer {
width: 300px;
height: 100px;
border: 1px solid black;
position: relative;
margin-bottom: 50px;
}
.absoluteContainer {
position: absolute;
width: 100vw; /* do a large number of px for ie8 compatibility*/
top: 0;
left: 0;
background-color: lightgray; /* just to show you what I've done*/
}
.contentContainer {
display: inline-block;
max-width: 400px; /* Word-break should happen here. */
border: 1px solid red;
}
Absolute container is directly related to the relative parent container.
There is no way to make an absolute container bigger (width or height) than a relative parent container.
If you want an absolute container bigger (width or height) than his parent the parent should not be relative.
Hope this help.
Have a good one
I don't think what you want to do is possible without using another class, or using JS. Here's how you can do it with css:
<div class="relativeContainer">
<div class="absoluteContainer bigger">
Hello you! This breaks on relativeContainers edge.. This is not what i want. It should just go further an further (until it reaches max-width of 400px).
</div>
</div>
<div class="relativeContainer">
<div class="absoluteContainer">
This should stay small.
</div>
</div>
.relativeContainer {
width: 300px;
height: 100px;
border: 1px solid black;
position: relative;
margin-bottom: 50px;
}
.absoluteContainer {
display: inline-block;
position: absolute;
top: 0;
left: 0;
max-width: 400px; /* Word-break should happen here. */
border: 1px solid red;
}
.absoluteContainer.bigger{
width: 400px;
}
I have looked at your example and I don't think you can do what you want if the absolute is inside the relative and you don't specify a width. Currently, with only a max-width, the inner absoluteContainer has no reason to go outside the relative container so it won't. Once you set a width, you get what you want but the small cannot stay small! You might be able to 'spoof' what you want by locating the absolute outside the relative but in the same location. This gives you something of what you want - but it won't (say) scroll the relative one if the absolute is bigger.
Example at: http://codepen.io/anon/pen/Nxovey
If you don't want to (or can't) identify longer text in CSS with extra classes then this is the best you can do without javascript.
Code:
<div class="spoofContainer">
<div class="absoluteContainer">
Hello you! This breaks on relativeContainers edge.. This is not what i want. It should just go further an further (until it reaches max-width of 400px).
</div>
</div>
<div class="relativeContainer">
</div>
<div class="spoofContainer">
<div class="absoluteContainer">
This should stay small.
</div>
</div>
<div class="relativeContainer">
</div>
CSS:
.spoofContainer {
width: 400px;
height: 0px;
overflow: visible;
position: relative;
}
.relativeContainer {
width: 300px;
height: 100px;
border: 1px solid black;
position: relative;
margin-bottom: 50px;
}
.absoluteContainer {
display: inline-block;
position: absolute;
top: 0;
left: 0;
max-width: 400px; /* Word-break should happen here. */
border: 1px solid red;
}

IE6 and IE7 absolute positioned div on top of multiple relative divs

Is it possible to make multiple absolute-positioned divs overlap multiple relative-positioned divs in IE6 & IE7?
See this jsFiddle for more information: http://jsfiddle.net/btker/1/
HTML
<div class="wrapper">
<div class="relative_div">Relative div.
<div class="absolute_div">This div have absolute position and is placed in a relative positioned div. This div should always be on top of all relative divs.</div>
</div>
</div>
<div class="wrapper">
<div class="relative_div">Relative div.
<div class="absolute_div">This div have absolute position and is placed in a relative positioned div. This div should always be on top of all relative divs.</div>
</div>
</div>
CSS
.wrapper{
height: 100%;
width: 100%;
}
.relative_div {
height: 75px;
width: 200px;
border: 1px solid #000;
padding: 10px;
background: #e6e6e6;
margin: 0 0 35px 0;
position: relative;
}
.absolute_div {
height: 100px;
width: 250px;
border: 1px solid #000;
background: #c6c6c6;
padding: 10px;
position: absolute;
top: 40px;
left: 100px;
z-index: 100;
}
There are two relative <div>s (placed in identical wrappers) containing each one a absolute <div> that overlap all the relative <div>s. This works great without any problems in updated versions of Chrome, Firefox etc, the absolute <div> with z-index is always placed on top.
In IE6 and IE7 this is not working. The different between this problem and the standard "dropdown in header display its menus behind the page content" is that in those situations its often fixed by give the parent element of that specific menu other z-index etc. In this case the both absolute <div>s are put in identical <div>s.
Can this be solved so the absolute <div>s are always on top of all relative <div>s in IE6 & IE7? Conditional comments for IE can be used to make the solution cross-browser.
It is possible but only by decreasing the z-index of the second .wrapper or increasing the z-index of the first .wrapper.
On a simple level, each positioned element with a non-auto z-index creates a new stacking context, although there are other circumstances in which a new stacking context is created - see The stacking context.
The problem is one that affects IE <= 7, from quirksmode.org
In Internet Explorer positioned elements generate a new stacking context, starting with a z-index value of 0. Therefore z-index doesn't work correctly.
CSS
.wrapper{
height: 100%;
width: 100%;
}
.lower {
position: relative;
z-index: -1;
}
.higher {
position: relative;
z-index: 2;
}
.relative_div {
height: 75px;
width: 200px;
border: 1px solid #000;
padding: 10px;
background: #e6e6e6;
margin: 0 0 35px 0;
position: relative;
}
.absolute_div {
height: 100px;
width: 250px;
border: 1px solid #000;
background: #c6c6c6;
padding: 10px;
position: absolute;
top: 40px;
left: 100px;
z-index: 1;
}
HTML
<div class="wrapper"> <!-- add higher class here -->
<div class="relative_div">Relative div.
<div class="absolute_div">This div have absolute position and is placed in a relative positioned div. This div should always be on top of all relative divs.</div>
</div>
</div>
<div class="wrapper"> <!-- or add lower class here -->
<div class="relative_div">Relative div.
<div class="absolute_div">This div have absolute position and is placed in a relative positioned div. This div should always be on top of all relative divs.</div>
</div>
</div>